/**
 * Created by zycool on 2016/10/13.
 * 封装 d3 常用图表
 * 如：折线图、柱状图、饼图、散点图
 */


/**
 * d3Charts 默认图表显示配置数据项
 * @type {{lineWidth: string, lineColor: string}}
 */
var d3Config = {
    lineWidth: '1.5px',                     // 线条宽度
    lineColor: '#5dadee',                   // 线条颜色(单条 蓝色)
    lineRender: 'crispEdges',               // 线条清晰度
    lineEdges: 'default',                   // 折线条清晰度

    circleBorder: '1.5px',                  // 线圈宽度
    circleFillColor: '#ffffff',             // 线圈填色
    circleBorderColor: '#5dadee',           // 线圈边框颜色

    gridColor: '#f0f0f0',                   // 网格颜色
    gridWidth: '1px',                       // 网格粗细

    areaBgColor: '#f6f7fe',                 // 区间背景色
    areaBgOpacity: 0.8,                     // 区间背景色透明度

    axisColor: '#5c5c5c',                   // 坐标轴颜色
    axisFontSize: '12px',                   // 坐标轴字体大小
    axisLong: 4,                            // 坐标轴刻度长度

    signCircleBorder: '2px',                // 标识边框宽度

    pointFillColor: '#48a2e8',              // 散点颜色

    scrollbarWidth: 0                       // 滚动条宽度
};


var d3Charts = {

    /**
     * 扩展一个对象
     * @param obj1
     * @param obj2
     * @returns {{}}
     */
    expand: function (obj1, obj2) {
        var obj = {};

        return obj;
    },


    /**
     * 从列表获取所需数据字段
     * @param list
     * @returns {Array} 返回如 [{x:1,y:y2},...]
     */
    formart: function (list, col, count, ys) {
        var arr = [];
        if (list) {
            if (Object.prototype.toString.call(list) === '[object Array]') {
                for (var i = 0, len = list.length; i < len; i++) {
                    var obj = {
                        x: 0,
                        y: 0,
                        ys: 0
                    };

                    if (list[i].hasOwnProperty(col['x'])) {
                        if (DyyBase.notEmpty(list[i][col['x']])) {
                            obj.x = list[i][col['x']]
                        } else {
                            obj.x = 0;
                        }
                    }

                    if (list[i].hasOwnProperty(col['y'])) {
                        if (DyyBase.notEmpty(list[i][col['y']])) {
                            obj.y = list[i][col['y']];
                        } else {
                            obj.y = 0;
                        }
                    }

                    if (ys) {
                        obj.ys = ys;
                    }

                    if (count && count === i) {
                        break;
                    }

                    arr.push(obj);
                }
            } else {
                throw new Error('数据格式不正确!');
            }
        } else {
            throw new Error('数据列表不存在!');
        }

        return arr;
    },


    /**
     * 怪异数据格式化,将y轴值为负数的转成正数
     * @param list
     * @param col
     * @param count
     * @returns {{x: Array, y: Array, ys: Array, index: Array, ticks: number}}
     */
    formartFx: function (list, col, count) {

        var data = {
            x: [],
            y: [],
            ys: [],
            ticks: 0,
            store: []
        };

        if (list) {
            if (Object.prototype.toString.call(list) === '[object Array]') {
                data.ticks = list.length;
                for (var i = 0, len = list.length; i < len; i++) {

                    var obj = {
                        x: 0,
                        y: 0,
                        ys: 0
                    };

                    if (list[i].hasOwnProperty(col['x'])) {
                        if (DyyBase.notEmpty(list[i][col['x']])) {
                            data.x.push(list[i][col['x']]);
                            obj.x = list[i][col['x']];
                        } else {
                            data.x.push(0);
                            obj.x = 0;
                        }
                    }

                    if (list[i].hasOwnProperty(col['y'])) {
                        if (DyyBase.notEmpty(list[i][col['y']])) {
                            var y = list[i][col['y']] < 0 ? (list[i][col['y']]) * -1 : list[i][col['y']];
                            data.y.push(y);
                            data.ys.push(list[i][col['y']]);
                            obj.y = y;
                            obj.ys = list[i][col['y']];
                        } else {
                            data.y.push(0);
                            data.ys.push(0);
                            obj.y = 0;
                            obj.ys = 0;
                        }
                    }

                    data.store.push(obj);

                    if (count && count === i) {
                        break;
                    }
                }
            } else {
                throw new Error('数据格式不正确!');
            }
        } else {
            throw new Error('数据列表不存在!');
        }

        return data;
    },


    /**
     * 怪异数据格式化, y值固定, ys 为标识
     * 内部数据格式化
     * 配合 formartYs 使用
     * @param list
     * @param col
     * @param count
     * @returns {{x: Array, y: Array, ys: Array, ticks: number, store: Array}}
     */
    formartSx: function (list, col, count) {

        var data = {
            x: [],
            y: [],
            ys: [],
            ticks: 0,
            store: []
        };

        if (list) {
            if (Object.prototype.toString.call(list) === '[object Array]') {
                data.ticks = list.length;
                for (var i = 0, len = list.length; i < len; i++) {

                    var obj = {
                        x: 0,
                        y: 0,
                        ys: 0
                    };

                    if (list[i].hasOwnProperty(col['x'])) {
                        if (DyyBase.notEmpty(list[i][col['x']])) {
                            data.x.push(list[i][col['x']]);
                            obj.x = list[i][col['x']];
                        } else {
                            data.x.push(0);
                            obj.x = 0;
                        }
                    }

                    if (list[i].hasOwnProperty(col['y'])) {
                        if (DyyBase.notEmpty(list[i][col['y']])) {
                            data.y.push(list[i][col['y']]);
                            obj.y = list[i][col['y']];
                        } else {
                            data.y.push(0);
                            obj.y = 0;
                        }
                    }

                    if (list[i].hasOwnProperty(col['ys'])) {
                        if (DyyBase.notEmpty(list[i][col['ys']])) {
                            data.ys.push(list[i][col['ys']]);
                            obj.ys = list[i][col['ys']];
                        } else {
                            data.ys.push(0);
                            obj.ys = 0;
                        }
                    }

                    data.store.push(obj);

                    if (count && count === i) {
                        break;
                    }
                }
            } else {
                throw new Error('数据格式不正确!');
            }
        } else {
            throw new Error('数据列表不存在!');
        }

        return data;
    },


    /**
     * 外部数据格式化
     * 配合 formartSx 使用
     * 返回 [{x:'',y:'',ys:''}]
     * @param list
     * @param col
     * @param count
     * @returns {Array}
     */
    formartYs: function (list, col, count) {
        var arr = [];
        if (list) {
            for (var i = 0, len = list.length; i < len; i++) {
                var obj = {
                    x: 0,
                    y: 0,
                    ys: 0
                };
                if (list[i].hasOwnProperty(col['x'])) {
                    if (list[i][col['x']] != null && list[i][col['x']] != undefined) {
                        obj.x = list[i][col['x']];
                    }
                }
                if (list[i].hasOwnProperty(col['y'])) {
                    if (list[i][col['y']] != null && list[i][col['y']] != undefined) {
                        obj.y = 1;
                        obj.ys = list[i][col['y']];
                    } else {
                        obj.y = 1;
                        obj.ys = 1;
                    }
                } else {
                    obj.y = 1;
                    obj.ys = 1;
                }
                arr.push(obj);
            }
        }
        return arr;
    },


    /**
     * 把 y 轴格式化成UTC时间
     * 注意: 只适用于时钟
     * @param list
     * @param col
     * @param count
     * @returns {Array}
     */
    formartTs: function (list, col, count) {
        var arr = [];
        if (list) {
            for (var i = 0, len = list.length; i < len; i++) {
                var obj = {
                    x: 0,
                    y: 0,
                    ys: 0
                };
                if (list[i].hasOwnProperty(col['x'])) {
                    if (list[i][col['x']] != null && list[i][col['x']] != undefined) {
                        obj.x = list[i][col['x']];
                    }
                }
                if (list[i].hasOwnProperty(col['y'])) {
                    if (list[i][col['y']] != null && list[i][col['y']] != undefined) {
                        var temp = (list[i][col['y']]).split(':');
                        temp[0] = parseInt(temp[0], 10);
                        temp[1] = parseInt(temp[1], 10);
                        obj.y = new Date(Date.UTC(2016, 10, 11, temp[0], temp[1]));
                    }
                }
                if (list[i].hasOwnProperty(col['ys'])) {
                    if (list[i][col['ys']] != null && list[i][col['ys']] != undefined) {
                        obj.ys = list[i][col['ys']];
                    }
                }
                arr.push(obj);
                if (count) {
                    if (count - 1 === i) {
                        break;
                    }
                }
            }
        }
        return arr;
    },


    /**
     * 返回 y 轴 百分比数据集
     * 外部使用
     * @param list
     * @param col
     * @param count
     * @returns {Array}
     */
    formartPercent: function (list, col, count) {
        var arr = [];
        if (list) {
            for (var i = 0, len = list.length; i < len; i++) {
                var obj = {
                    x: 0,
                    y: 0
                };
                if (list[i].hasOwnProperty(col['x'])) {
                    if (list[i][col['x']] != null && list[i][col['x']] != undefined) {
                        obj.x = list[i][col['x']];
                    }
                }
                if (list[i].hasOwnProperty(col['a']) && list[i].hasOwnProperty(col['b'])) {
                    if (list[i][col['a']] != null && list[i][col['b']] != null) {
                        obj.y = DyyBase.getPercent(list[i][col['a']], list[i][col['b']]);
                    }
                }
                arr.push(obj);
                if (count) {
                    if (count - 1 === i) {
                        break;
                    }
                }
            }
        }
        return arr;
    },


    /**
     * 返回 x 轴区间数据
     * 外部使用
     * @param list
     * @param col
     * @param count
     * @returns {Array}
     */
    formartX1X2: function (list, col, count) {
        var arr = [];
        if (list) {
            for (var i = 0, len = list.length; i < len; i++) {
                var obj = {
                    x1: 0,
                    x2: 0,
                    y: 0
                };
                if (list[i].hasOwnProperty(col['x1'])) {
                    if (list[i][col['x1']] != null && list[i][col['x1']] != undefined) {
                        obj.x1 = list[i][col['x1']];
                    }
                }
                if (list[i].hasOwnProperty(col['x2'])) {
                    if (list[i][col['x2']] != null && list[i][col['x2']] != undefined) {
                        obj.x2 = list[i][col['x2']];
                    }
                }
                if (list[i].hasOwnProperty(col['y'])) {
                    if (list[i][col['y']] != null && list[i][col['y']] != undefined) {
                        obj.y = list[i][col['y']];
                    }
                }
                arr.push(obj);
                if (count) {
                    if (count - 1 === i) {
                        break;
                    }
                }
            }
        }
        return arr;
    },


    /**
     * 返回 x 轴区间
     * 内部使用
     * @param list
     * @param col
     * @param count
     * @returns {{x1: Array, x2: Array, y: Array, ys: Array, store: Array}}
     */
    formartX1X2YS: function (list, col, count) {
        var obj = {
            x: [],
            x1: [],
            x2: [],
            y: [],
            ys: [],
            store: [],
            ticks: 0
        };
        if (list) {
            obj.ticks = list.length;
            for (var i = 0, len = list.length; i < len; i++) {
                var temp = {
                    x1: 0,
                    x2: 0,
                    y: 0,
                    ys: 0
                };
                if (list[i].hasOwnProperty(col['x1'])) {
                    if (list[i][col['x1']] != null && list[i][col['x1']] != undefined) {
                        obj.x.push(list[i][col['x1']]);
                        obj.x1.push(list[i][col['x1']]);
                        temp.x1 = list[i][col['x1']];
                    }
                }
                if (list[i].hasOwnProperty(col['x2'])) {
                    if (list[i][col['x2']] != null && list[i][col['x2']] != undefined) {
                        obj.x.push(list[i][col['x2']]);
                        obj.x2.push(list[i][col['x2']]);
                        temp.x2 = list[i][col['x2']];
                    }
                }
                if (list[i].hasOwnProperty(col['y'])) {
                    if (list[i][col['y']] != null && list[i][col['y']] != undefined) {
                        obj.ys.push(list[i][col['y']]);
                        temp.ys = list[i][col['y']];
                    }
                }
                obj.y.push(1);
                temp.y = 1;
                obj.store.push(temp);
                if (count) {
                    if (count - 1 === i) {
                        break;
                    }
                }
            }
        }
        return obj;
    },


    /**
     * 返回 x 区间
     * @param list 当list为数组时 [1,2,3]
     * @param count
     * @returns {{x: Array, y: Array, ticks: number, index: Array, store: Array}}
     */
    formartX1X2Y: function (list, count) {
        var obj = {
            x: {
                data: [],
                index: [],
                ticks: 0
            },
            y: {
                data: [],
                index: [],
                ticks: 0
            },
            store: []
        };
        if (list) {
            for (var i = 0, len = list.length; i < len; i++) {
                var x1 = list[i][0];
                var x2 = list[i][1];
                var y = list[i][2];
                obj.x.data.push(x1);
                obj.x.data.push(x2);
                obj.x.index.push(i);

                obj.y.data.push(y);
                obj.y.index.push(i);

                obj.store.push([[x1, y], [x2, y]]);

                if (count) {
                    if (count - 1 === i) {
                        break;
                    }
                }
            }

            obj.x.ticks = list.length;
            obj.y.ticks = list.length;
        }
        return obj;
    },


    /**
     * 获取浏览器滚动条宽度
     * @returns {number|*}
     */
    getScrollbarWidth: function () {
        var oP = document.createElement('p'),
            styles = {
                width: '100px',
                height: '100px',
                overflowY: 'scroll'
            }, i, scrollbarWidth;
        for (i in styles) oP.style[i] = styles[i];
        oP.setAttribute('id', 'D3_test_scroll_bar');
        document.body.appendChild(oP);
        scrollbarWidth = oP.offsetWidth - oP.clientWidth;
        document.body.removeChild(oP);
        return scrollbarWidth;
    },


    /**
     * 显示提示 - 如鼠标移动到点或线上时
     * @param flag 标识提示框是否显示(true 显示 false 隐藏)
     * @param ent d3.event
     * @param dom 当前触发事件domm
     * @param tip defaults tip 对象
     * @param margin 外边距,还用来计算鼠标临界点
     * @param content 提示内容
     */
    showTip: function (flag, ent, dom, tip, margin, content) {
        var self = this;
        var dom_tip = document.getElementById('DM_d3_tip');
        if (flag) {
            var d3dom = d3.select(dom);
            var x_data = d3dom.attr('data-x'), y_data = d3dom.attr('data-y');
            if(x_data && y_data){
                document.body.style.overflowX = 'hidden';
                var page_x = parseFloat(ent.pageX) || parseFloat(ent.clientX);
                var page_y = parseFloat(ent.pageY) || parseFloat(ent.clientY);

                // 计算是否是最后一个临界点 - start
                var doc_w = parseFloat(document.body.clientWidth);
                if (!d3Config.scrollbarWidth) {
                    d3Config.scrollbarWidth = self.getScrollbarWidth();
                }
                var space = doc_w - 45 - d3Config.scrollbarWidth;
                if (margin) {
                    space = space - margin.right;
                }
                if (page_x >= space) {
                    page_x = page_x - 160 - margin.right;
                }
                // 计算是否是最后一个临界点 - end

                var info = '';
                if (tip) {
                    if (content) {
                        info = content;
                        page_y = page_y + 20;
                    } else {
                        if (tip.xtag) {
                            info += tip.xtag + '：' + x_data + '<br>';
                            page_y = page_y - 10;
                        }
                        if (tip.ytag) {
                            info += tip.ytag + '：' + y_data;
                            page_y = page_y - 40;
                        }
                    }
                }
                if (dom_tip) {
                    dom_tip.innerHTML = info;
                    dom_tip.style.top = page_y + 'px';
                    dom_tip.style.left = page_x + 'px';
                    dom_tip.style.display = 'block';
                } else {
                    dom_tip = document.createElement('div');
                    dom_tip = document.body.appendChild(dom_tip);
                    dom_tip.innerHTML = info;
                    dom_tip.setAttribute('id', 'DM_d3_tip');
                    dom_tip.setAttribute('class', 'd3-tip-box');
                    dom_tip.style.top = page_y + 'px';
                    dom_tip.style.left = page_x + 'px';
                    dom_tip.style.display = 'block';
                }
            }else{
                document.body.removeAttribute('style');
                if (dom_tip) {
                    dom_tip.style.display = 'none';
                }
            }
        } else {
            document.body.removeAttribute('style');
            if (dom_tip) {
                dom_tip.style.display = 'none';
            }
        }
    },

    /**
     * 获取x,y轴数据 - 多个对象数组
     * @param data x 值为连续数值
     * @returns {{x: Array, y: Array}}
     */
    axisFill: function (data) {
        var axis = {
            x: {
                data: [],
                ticks: 0,
                index: []
            },
            y: {
                data: [],
                ticks: 0,
                index: []
            },
            store: []
        };

        var chk = -1;

        var len = data.length;
        if (len > 0) {
            for (var i = 0; i < len; i++) {
                if (Object.prototype.toString.call(data[i]) === '[object Array]') {
                    // 检测多个数据长度是否一致
                    var lenth = data[i].length;
                    if (chk === -1) {
                        chk = lenth;
                        axis['x']['ticks'] = axis['y']['ticks'] = chk;
                        axis['x']['index'] = axis['y']['index'] = d3.range(lenth);
                    }
                    if (chk !== lenth) {
                        //throw new Error('多个数据长度不一致!');
                    }
                    if (lenth > 0) {
                        var arr = [];
                        for (var j = 0; j < lenth; j++) {
                            if (data[i][j].hasOwnProperty('x') && data[i][j].hasOwnProperty('y')) {
                                var obj = {};
                                obj.x = data[i][j]['x'];
                                obj.y = data[i][j]['y'];
                                obj.index = j;
                                arr.push(obj);
                                axis['y']['data'].push(obj.y);
                                if (i === 0) {
                                    axis['x']['data'].push(obj.x);
                                }
                            }
                        }
                        axis['store'].push(arr);
                    }
                } else {
                    throw new Error('多个x,y轴数据格式不正确!');
                }
            }
        } else {
            throw new Error('多个x,y轴数据长度为0!');
        }

        return axis;
    },

    /**
     * 获取x,y轴数据 - 单个对象数组
     * @param data x 值为数字型
     * @returns {{x: Array, y: Array}}
     */
    axisData: function (data) {
        var axis = {
            x: {
                data: [],
                ticks: 0,
                index: []
            },
            y: {
                data: [],
                ticks: 0,
                index: []
            },
            store: []
        };

        if (data) {
            if (Object.prototype.toString.call(data) === '[object Array]') {
                var len = data.length;
                if (len > 0) {
                    var temp = data[0];
                    // 单个对象数组
                    if (Object.prototype.toString.call(temp) === '[object Object]') {
                        for (var i = 0; i < len; i++) {
                            if (data[i].hasOwnProperty('x') && data[i].hasOwnProperty('y') || data[i].hasOwnProperty('ys')) {
                                var x = (data[i]['x'] !== undefined && data[i]['x'] !== null) ? data[i]['x'] : 0;
                                var y = (data[i]['y'] !== undefined && data[i]['y'] !== null) ? data[i]['y'] : 0;
                                var ys = (data[i]['ys'] !== undefined && data[i]['ys'] !== null) ? data[i]['ys'] : 0;
                                var obj = {};

                                obj.x = x;
                                obj.y = y;
                                obj.ys = ys;
                                obj.index = i;

                                axis['store'].push(obj);
                                axis['x']['data'].push(x);
                                axis['y']['data'].push(y);
                                axis['x']['index'].push(i);
                                axis['y']['index'].push(i);
                            } else {
                                throw new Error('x,y轴数据不存在!');
                            }
                        }
                        axis['x']['ticks'] = axis['y']['ticks'] = len;
                    }
                    // 多个对象数组
                    if (Object.prototype.toString.call(temp) === '[object Array]') {
                        axis = this.axisFill(data);
                    }
                } else {
                    throw new Error('x,y轴数据长度为0!');
                }
            } else {
                throw new Error('x,y轴数据格式不正确!');
            }
        } else {
            throw new Error('所需x,y轴数据不存在!');
        }

        return axis;
    },

    /**
     * 获取画布容器高宽
     * @param domId
     * @returns {{width: number, height: number}}
     */
    area: function (domId) {
        var size = {
            width: 500,
            height: 400
        };

        var dom = document.getElementById(domId);
        if (dom) {
            dom.innerHTML = '';
            var w = dom.style.width, h = dom.style.height;
            if (w && h) {
                size.width = parseInt(w.replace('px', ''));
                size.height = parseInt(h.replace('px', ''));
                return size;
            }
        } else {
            throw new Error(domId + ' DOM容器不存在!');
        }

        return size;
    },


    /**
     * 返回一个d3线性比例尺
     * @param options
     * @returns {*}
     */
    getScale: function(options){
        var self = this;
        var defaults = {
            d_min: 0,
            d_max: 10,
            r_min: 0,
            r_max: 10,
            nice: false
        };
        var settings = options || defaults;
        var xScale = d3.scaleLinear()
            .domain([settings.d_min, settings.d_max])
            .range([settings.r_min, settings.r_max]);
        if(settings.nice){
            xScale.nice();
        }
        return xScale;
    },


    /**
     * 画折线图 x 轴为数值型
     * @param config
     * @returns {boolean}
     */
    dogLeg: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#04adee'],              // 折线颜色
            xAxis: {                         // x轴
                data: [],                    // x轴数据
                ticks: 0,                    // x轴刻度数
                index: [],                   // x轴索引
                render: '',                  // 渲染回调函数
                show: true,                  // 是否显示(默认true)
                orient: 'bottom',            // x轴方向(默认bottom)
                sort: 'asc'                  // 刻度排序(默认上升asc)
            },
            yAxis: {                         // y轴
                data: [],
                ticks: 0,
                index: [],
                render: '',
                show: true,
                orient: 'left',
                sort: 'asc'
            },
            store: [],                       // 格式化后的数据集
            data: [],                        // 原始数据集
            layout: {
                xtag: 'x轴',                 // x轴显示文本
                ytag: 'y轴',                 // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                           // 距容器边距
                xgrid: false,                // x轴网格
                ygrid: false                 // y轴网格
            },
            areaShow: false,                 // 是否显示区间背景(默认false不显示)
            area: [],                        // 区间背景
            pointText: {
                show: false,                 // 节点文字是否显示(默认true显示)
                render: '',                  // 渲染回调函数
                circle: false,               // 节点圆圈是否显示(默认true显示)
                startShow: false,            // 显示折线开始节点圆圈(默认false不显示)
                stopShow: false              // 显示折线结束节点圆圈(默认false不显示)
            },
            tip: {
                show: false,
                xtag: 'x轴',
                ytag: 'y轴'
            },
            path: {                          // 折线类型是否加area背景(目前只有area)
                show: false,                 // 默认不显示(false)
                type: 'area',
                color: ['#ff0000', '#ff5500']
            }
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('area')) {
                    defaults.area = config['area'];
                }

                if (config.hasOwnProperty('areaShow')) {
                    defaults.areaShow = config['areaShow'];
                }

                if (config.hasOwnProperty('path')) {
                    if (config['path'].hasOwnProperty('show')) {
                        defaults.path.show = config['path']['show'];
                    }
                    if (config['path'].hasOwnProperty('type')) {
                        defaults.path.type = config['path']['type'];
                    }
                    if (config['path'].hasOwnProperty('color')) {
                        defaults.path.color = config['path']['color'];
                    }
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('index')) {
                        defaults.xAxis.index = config['xAxis']['index'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('orient')) {
                        defaults.xAxis.orient = config['xAxis']['orient'];
                    }
                    if (config['xAxis'].hasOwnProperty('sort')) {
                        defaults.xAxis.sort = config['xAxis']['sort'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('index')) {
                        defaults.yAxis.index = config['yAxis']['index'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('orient')) {
                        defaults.yAxis.orient = config['yAxis']['orient'];
                    }
                    if (config['yAxis'].hasOwnProperty('sort')) {
                        defaults.yAxis.sort = config['yAxis']['sort'];
                    }
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.render = config['pointText']['render'];
                    }
                    if (config['pointText'].hasOwnProperty('circle')) {
                        defaults.pointText.circle = config['pointText']['circle'];
                    }
                    if (config['pointText'].hasOwnProperty('startShow')) {
                        defaults.pointText.startShow = config['pointText']['startShow'];
                    }
                    if (config['pointText'].hasOwnProperty('stopShow')) {
                        defaults.pointText.stopShow = config['pointText']['stopShow'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var areaSize = this.area(defaults.container);
        var width = areaSize.width;
        var height = areaSize.height;

        // get axis data
        var axisData = this.axisData(defaults.data);

        // set store data
        if (defaults.store.length === 0) {
            defaults.store = axisData.store;
        }

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x.data;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y.data;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.x.ticks;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.y.ticks;
        }

        // set axis index
        if (defaults.xAxis.index.length === 0) {
            defaults.xAxis.index = axisData.x.index;
        }

        if (defaults.yAxis.index.length === 0) {
            defaults.yAxis.index = axisData.y.index;
        }

        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale
        var xScale;
        if (defaults.xAxis.sort === 'asc') {
            xScale = d3.scaleLinear()
                .domain([d3.min(defaults.xAxis.data), d3.max(defaults.xAxis.data)])
                .range([0, width - defaults.layout.margin.left - defaults.layout.margin.right])
                .nice();
        } else if (defaults.xAxis.sort === 'desc') {
            xScale = d3.scaleLinear()
                .domain([d3.min(defaults.xAxis.data), d3.max(defaults.xAxis.data)])
                .range([width - defaults.layout.margin.left - defaults.layout.margin.right, 0])
                .nice();
        }

        // yScale
        var yScale;
        if (defaults.yAxis.sort === 'asc') {
            yScale = d3.scaleLinear()
                .domain([d3.min(defaults.yAxis.data), d3.max(defaults.yAxis.data)])
                .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
                .nice();
        } else if (defaults.yAxis.sort === 'desc') {
            yScale = d3.scaleLinear()
                .domain([d3.max(defaults.yAxis.data), d3.min(defaults.yAxis.data)])
                .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
                .nice();
        }

        // xAxis
        var xAxis;
        if (defaults.xAxis.orient === 'bottom') {
            if (defaults.xAxis.ticks === Infinity) {
                xAxis = d3.axisBottom(xScale);
            } else {
                xAxis = d3.axisBottom(xScale)
                    .ticks(defaults.xAxis.ticks);
            }
        } else if (defaults.xAxis.orient === 'top') {
            if (defaults.xAxis.ticks === Infinity) {
                xAxis = d3.axisTop(xScale)
            } else {
                xAxis = d3.axisTop(xScale)
                    .ticks(defaults.xAxis.ticks);
            }
        }

        // yAxis
        var yAxis;
        if (defaults.yAxis.orient === 'left') {
            if (defaults.yAxis.ticks === Infinity) {
                yAxis = d3.axisLeft(yScale);
            } else {
                yAxis = d3.axisLeft(yScale)
                    .ticks(defaults.yAxis.ticks);
            }
        } else if (defaults.yAxis.orient === 'right') {
            if (defaults.yAxis.ticks === Infinity) {
                yAxis = d3.axisRight(yScale);
            } else {
                yAxis = d3.axisRight(yScale)
                    .ticks(defaults.yAxis.ticks);
            }
        }

        // xGrid
        var xGrid;
        if (defaults.xAxis.orient === 'bottom') {
            if (defaults.xAxis.ticks === Infinity) {
                xGrid = d3.axisBottom(xScale)
                    .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom]);
            } else {
                xGrid = d3.axisBottom(xScale)
                    .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom])
                    .ticks(defaults.xAxis.ticks);
            }
        } else if (defaults.xAxis.orient === 'top') {
            if (defaults.xAxis.ticks === Infinity) {
                xGrid = d3.axisTop(xScale)
                    .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom]);
            } else {
                xGrid = d3.axisTop(xScale)
                    .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom])
                    .ticks(defaults.xAxis.ticks);
            }
        }

        // yGrid
        var yGrid;
        if (defaults.yAxis.orient === 'left') {
            if (defaults.yAxis.ticks === Infinity) {
                yGrid = d3.axisRight(yScale)
                    .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right]);
            } else {
                yGrid = d3.axisRight(yScale)
                    .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right])
                    .ticks(defaults.yAxis.ticks);
            }
        } else if (defaults.yAxis.orient === 'right') {
            if (defaults.yAxis.ticks === Infinity) {
                yGrid = d3.axisLeft(yScale)
                    .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right]);
            } else {
                yGrid = d3.axisLeft(yScale)
                    .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right])
                    .ticks(defaults.yAxis.ticks);
            }
        }


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var x_xg = 0, y_xg = 0;
            if (defaults.xAxis.orient === 'bottom') {
                x_xg = defaults.layout.margin.left;
                y_xg = defaults.layout.margin.top;
            } else if (defaults.xAxis.orient === 'top') {
                x_xg = defaults.layout.margin.left;
                y_xg = height - defaults.layout.margin.top;
            }
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + x_xg + ',' + y_xg + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var x_yg = 0, y_yg = 0;
            if (defaults.yAxis.orient === 'left') {
                x_yg = defaults.layout.margin.left;
                y_yg = defaults.layout.margin.top;
            } else if (defaults.yAxis.orient === 'right') {
                x_yg = width - defaults.layout.margin.left;
                y_yg = defaults.layout.margin.top;
            }
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + x_yg + ',' + y_yg + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加区间背景 - start ---------*/
        if (defaults.areaShow) {
            var lens = defaults.area.length;
            var bg_w = 0, bg_h = 0, bg_y = 0;
            if (lens > 0) {
                var y_ticks_arr = yScale.ticks();
                var y_max_tick = d3.max(y_ticks_arr);
                var y_min_tick = d3.min(y_ticks_arr);
                for (var n = 0; n < lens; n++) {
                    bg_w = width - defaults.layout.margin.left - defaults.layout.margin.right;
                    if(defaults.area[n].range[0]){
                        if(defaults.area[n].range[0] < y_min_tick){
                            defaults.area[n].range[0] = y_min_tick;
                        }
                        bg_y = (yScale(defaults.area[n].range[0]) + defaults.layout.margin.top);
                    }
                    if(defaults.area[n].range[1]){
                        if(defaults.area[n].range[1] > y_max_tick){
                            defaults.area[n].range[1] = y_max_tick;
                        }
                        bg_h = Math.abs(yScale(defaults.area[n].range[1]) - yScale(defaults.area[n].range[0]));
                        bg_y = (yScale(defaults.area[n].range[1]) + defaults.layout.margin.top);
                    }else{
                        bg_h = 1;
                    }

                    bg_y = parseInt(bg_y);

                    svg.append('g')
                        .attr('class', 'zy-area-bg')
                        .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + bg_y + ')')
                        .append('rect')
                        .attr('width', bg_w)
                        .attr('height', bg_h)
                        .attr('opacity', 0.8)
                        .attr('fill', defaults.area[n].background);

                    if (defaults.area[n].text) {
                        svg.append('g')
                            .attr('class', 'zy-area-text')
                            .attr('transform', 'translate(' + (width - defaults.layout.margin.right / 2) + ',' + (bg_y + 12) + ')')
                            .selectAll('text')
                            .data(defaults.area[n].text)
                            .enter()
                            .append('text')
                            .text(function (d) {
                                return d;
                            })
                            .attr('font-size', d3Config.axisFontSize)
                            .attr('fill', d3Config.axisColor)
                            .attr('y', function (d, i) {
                                return i * 12;
                            });
                    }
                }
            } else {
                bg_w = width - defaults.layout.margin.left - defaults.layout.margin.right;
                bg_h = height - defaults.layout.margin.top - defaults.layout.margin.bottom;

                svg.append('g')
                    .attr('class', 'zy-area-bg')
                    .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
                    .append('rect')
                    .attr('width', bg_w)
                    .attr('height', bg_h)
                    .attr('opacity', 0.8)
                    .attr('fill', d3Config.areaBgColor);
            }
        }
        /*--------- 添加区间背景 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var x_xa = 0, y_xa = 0;
            if (defaults.xAxis.orient === 'bottom') {
                x_xa = defaults.layout.margin.left;
                y_xa = height - defaults.layout.margin.bottom;
            } else if (defaults.xAxis.orient === 'top') {
                x_xa = defaults.layout.margin.left;
                y_xa = defaults.layout.margin.top;
            }
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + x_xa + ',' + y_xa + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .text(function (d) {
                    if (defaults.xAxis.render instanceof Function) {
                        return defaults.xAxis.render(d);
                    } else {
                        return d;
                    }
                })
                .attr('font-size', d3Config.axisFontSize)
                .attr('fill', d3Config.axisColor);

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

        }

        if (defaults.yAxis.show) {
            var x_ya = 0, y_ya = 0;
            if (defaults.yAxis.orient === 'left') {
                x_ya = defaults.layout.margin.left;
                y_ya = defaults.layout.margin.top;
            } else if (defaults.yAxis.orient === 'right') {
                x_ya = width - defaults.layout.margin.left;
                y_ya = defaults.layout.margin.top;
            }
            var yaxis = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + x_ya + ',' + y_ya + ')')
                .call(yAxis);

            yaxis.selectAll('text')
                .text(function (d) {
                    if (defaults.yAxis.render instanceof Function) {
                        return defaults.yAxis.render(d);
                    } else {
                        return d;
                    }
                })
                .attr('font-size', d3Config.axisFontSize)
                .attr('fill', d3Config.axisColor);

            yaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            var x_xt = 0, y_xt = 0;
            if (defaults.xAxis.orient === 'bottom') {
                x_xt = width / 2;
                y_xt = height - defaults.layout.margin.bottom / 10;
            } else if (defaults.xAxis.orient === 'top') {
                x_xt = width - defaults.layout.margin.right * 3;
                y_xt = defaults.layout.margin.top / 3;
            }
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + x_xt + ',' + y_xt + ')')
                .append('text')
                .text(defaults.layout.xtag)
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);
        }

        if (defaults.layout.ytag) {
            var x_yt = 0, y_yt = 0;
            if (defaults.yAxis.orient === 'left') {
                if (defaults.xAxis.orient === 'bottom') {
                    x_yt = 0;
                    y_yt = defaults.layout.margin.top - 10;
                } else if (defaults.xAxis.orient === 'top') {
                    x_yt = 0;
                    y_yt = height - defaults.layout.margin.bottom / 3;
                }
            } else if (defaults.yAxis.orient === 'right') {
                x_yt = width - defaults.layout.margin.right;
                y_yt = height - defaults.layout.margin.bottom / 3;
            }
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + x_yt + ',' + y_yt + ')')
                .append('text')
                .text(defaults.layout.ytag)
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加折线背景 - start ---------*/
        if (defaults.path.show) {
            var areafun = d3.area()
                .x(function (d) {
                    return xScale(d.x);
                })
                .y0(height - defaults.layout.margin.top - defaults.layout.margin.bottom)
                .y1(function (d) {
                    return yScale(d.y);
                });

            var areabg = svg.append('linearGradient')
                .attr('id', 'zy_path_area')
                .attr('x1', '100%')
                .attr('y1', '100%')
                .attr('x2', '100%')
                .attr('y2', '0%');

            areabg.append('stop')
                .attr('offset', '0%')
                .style('stop-color', defaults.path.color[1])
                .style('stop-opacity', '0');

            areabg.append('stop')
                .attr('offset', '100%')
                .style('stop-color', defaults.path.color[0])
                .style('stop-opacity', '0.1');

            svg.append('path')
                .datum(defaults.data)
                .attr('class', 'zy-path-areabg')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .attr('d', areafun)
                .attr('fill', 'url(#zy_path_area)');
        }
        /*--------- 添加折线背景 - end ---------*/


        /*--------- 添加折线 - start ---------*/
        var temp = defaults.data[0];
        var line = d3.line()
            .x(function (d) {
                return xScale(d.x);
            })
            .y(function (d) {
                return yScale(d.y);
            });
        // 单条
        if (Object.prototype.toString.call(temp) === '[object Object]') {
            var path = svg.append('path')
                .attr('class', 'zy-line-path')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .attr('d', line(defaults.data))
                .attr('stroke', defaults.color[0])
                .attr('fill', 'none')
                .attr('stroke-width', d3Config.lineWidth)
                .attr('shape-rendering', d3Config.lineEdges);
        }
        // 多条
        if (Object.prototype.toString.call(temp) === '[object Array]') {
            for (var i = 0, len = defaults.data.length; i < len; i++) {
                var line_color = '#000000';
                if (defaults.color[i]) {
                    line_color = defaults.color[i];
                }
                var paths = svg.append('path')
                    .attr('class', 'zy-line-path')
                    .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                    .attr('d', line(defaults.data[i]))
                    .attr('stroke', line_color)
                    .attr('fill', 'none')
                    .attr('stroke-width', d3Config.lineWidth)
                    .attr('shape-rendering', d3Config.lineEdges);

            }
        }
        /*--------- 添加折线 - end ---------*/


        /*--------- 添加圆圈 - start ---------*/
        if (defaults.pointText.circle) {
            // 单组
            if (Object.prototype.toString.call(temp) === '[object Object]') {
                var circle = svg.append('g')
                    .attr('class', 'zy-circle')
                    .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                    .selectAll('circle')
                    .data(defaults.data)
                    .enter()
                    .append('circle')
                    .attr('cx', line.x())
                    .attr('cy', line.y())
                    .attr('r', 3)
                    .attr('stroke', defaults.color[0])
                    .attr('fill', d3Config.circleFillColor)
                    .attr('stroke-width', d3Config.circleBorder)
                    .attr('data-x', function (d) {
                        return d.x;
                    })
                    .attr('data-y', function (d) {
                        return d.y;
                    })
                    .on('mouseover', function () {
                        d3.select(this)
                            .attr('r', 4);

                        if (defaults.tip.show) {
                            self.showTip(true, d3.event, this, defaults.tip, defaults.layout.margin);
                        }
                    })
                    .on('mouseout', function () {
                        d3.select(this)
                            .attr('r', 3);

                        if (defaults.tip.show) {
                            self.showTip(false);
                        }
                    });
            }
            // 多组
            if (Object.prototype.toString.call(temp) === '[object Array]') {
                for (var j = 0, lenth = defaults.data.length; j < lenth; j++) {
                    var circle_color = '#000000';
                    if (defaults.color[j]) {
                        circle_color = defaults.color[j];
                    }
                    var circles = svg.append('g')
                        .attr('class', 'zy-circle')
                        .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                        .selectAll('circle')
                        .data(defaults.data[j])
                        .enter()
                        .append('circle')
                        .attr('cx', line.x())
                        .attr('cy', line.y())
                        .attr('r', 3)
                        .attr('stroke', circle_color)
                        .attr('fill', d3Config.circleFillColor)
                        .attr('stroke-width', d3Config.circleBorder)
                        .attr('data-x', function (d) {
                            return d.x;
                        })
                        .attr('data-y', function (d) {
                            return d.y;
                        })
                        .on('mouseover', function () {
                            d3.select(this)
                                .attr('r', 4);

                            if (defaults.tip.show) {
                                self.showTip(true, d3.event, this, defaults.tip, defaults.layout.margin);
                            }
                        })
                        .on('mouseout', function () {
                            d3.select(this)
                                .attr('r', 3);

                            if (defaults.tip.show) {
                                self.showTip(false);
                            }
                        });
                }
            }
        }
        /*--------- 添加圆圈 - end ---------*/


        /*--------- 添加首尾圆圈 - start ---------*/
        if (defaults.pointText.startShow && defaults.pointText.stopShow) {
            var start_stop_circle = [
                {
                    x: axisData.x.data[0],
                    y: axisData.y.data[0]
                },
                {
                    x: axisData.x.data[(axisData.x.data.length - 1)],
                    y: axisData.y.data[(axisData.y.data.length - 1)]
                }
            ];

            svg.append('g')
                .attr('class', 'zy-start-stop-circle')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .selectAll('circle')
                .data(start_stop_circle)
                .enter()
                .append('circle')
                .attr('cx', line.x())
                .attr('cy', line.y())
                .attr('r', 3)
                .attr('stroke', defaults.color[0])
                .attr('fill', d3Config.circleFillColor)
                .attr('stroke-width', d3Config.circleBorder)
                .attr('data-x', function (d) {
                    return d.x;
                })
                .attr('data-y', function (d) {
                    return d.y;
                })
                .on('mouseover', function () {
                    d3.select(this)
                        .attr('r', 4);

                    self.showTip(true, d3.event, this, defaults.tip, defaults.layout.margin);
                })
                .on('mouseout', function () {
                    d3.select(this)
                        .attr('r', 3);

                    self.showTip(false);
                });
        }
        /*--------- 添加首尾圆圈 - end ---------*/


        /*--------- 添加圆圈文字 - start ---------*/
        var x_cx = 0, y_cy = 0;
        if (defaults.xAxis.orient === 'bottom') {
            x_cx = defaults.layout.margin.left - 8;
            y_cy = defaults.layout.margin.top - 14;
        } else if (defaults.xAxis.orient === 'top') {
            x_cx = defaults.layout.margin.left - 8;
            y_cy = defaults.layout.margin.top + 20;
        }
        if (defaults.pointText.show) {
            // 单组
            if (Object.prototype.toString.call(temp) === '[object Object]') {
                svg.append('g')
                    .attr('class', 'zy-circle-text')
                    .attr('transform', 'translate(' + x_cx + ',' + y_cy + ')')
                    .selectAll('text')
                    .data(defaults.data)
                    .enter()
                    .append('text')
                    .text(function (d) {
                        return d.y;
                    })
                    .attr('x', line.x())
                    .attr('y', line.y())
                    .attr('fill', d3Config.axisColor)
                    .attr('font-size', d3Config.axisFontSize);
            }
            // 多组
            if (Object.prototype.toString.call(temp) === '[object Array]') {
                for (var k = 0, lenths = defaults.data.length; k < lenths; k++) {
                    svg.append('g')
                        .attr('class', 'zy-circle-text')
                        .attr('transform', 'translate(' + x_cx + ',' + y_cy + ')')
                        .selectAll('text')
                        .data(defaults.data[k])
                        .enter()
                        .append('text')
                        .text(function (d) {
                            return d.y;
                        })
                        .attr('x', line.x())
                        .attr('y', line.y())
                        .attr('fill', d3Config.axisColor)
                        .attr('font-size', d3Config.axisFontSize);
                }
            }
        }
        /*--------- 添加圆圈文字 - end ---------*/


        /*--------- 添加鼠标遮盖范围 - start ---------*/
        if (defaults.tip.show) {
            var tipg = svg.append('g')
                .attr('class', 'zy-overlay-tip')
                .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')');

            var tipline = tipg.append('line')
                .attr('y1', 0)
                .attr('y2', height - defaults.layout.margin.top - defaults.layout.margin.bottom)
                .attr('opacity', 0)
                .attr('stroke', '#909090')
                .attr('stroke-width', '1px')
                .attr('stroke-dasharray', '5,2')
                .attr('shape-rendering', 'crispEdges');

            var tipdot = svg.append('g')
                .attr('class', 'zy-overlay-dot')
                .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')');

            var overlay = svg.append('g')
                .attr('class', 'zy-overlay-rect')
                .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
                .append('rect')
                .attr('width', width - defaults.layout.margin.left)
                .attr('height', height - defaults.layout.margin.top - defaults.layout.margin.bottom)
                .attr('fill', 'none')
                .style('pointer-events', 'all');

            // this is a bad method
            var ticks_arr = xScale.ticks();
            var ticks_num = 0;
            try{
                ticks_num = Math.abs(ticks_arr[1] - ticks_arr[0]);
                ticks_num = ticks_num / 2;
            }catch (e){
                throw new Error(e.message);
            }

            overlay.on('mousemove', function () {
                var pos = d3.mouse(this);
                var x = xScale.invert(pos[0]);

                var dots = tipdot.selectAll('circle');

                if (defaults.store.length > 0) {
                    var len_ab = defaults.store.length;
                    var dot_arr = [];
                    for (var ai = 0; ai < len_ab; ai++) {
                        for(var ci = 0, len_cd = defaults.store[ai].length; ci < len_cd; ci++){
                            if(dot_arr.length == len_ab){
                                break;
                            }
                            var store_x = defaults.store[ai][ci]['x'];
                            if(store_x < x + ticks_num && store_x > x - ticks_num){
                                var index = defaults.store[ai][ci]['index'];
                                var x_v = defaults.store[ai][ci]['x'];
                                var y_v = defaults.store[ai][ci]['y'];
                                dot_arr.push([x_v, y_v, index]);
                            }
                        }
                    }

                    if (dots._groups[0].length > 0) {
                        dots.datum(dot_arr).attr('cx', function (d, i) {
                            // append dom data for tip show
                            if (d && d[i]) {
                                overlay.attr('data-x', d[0][0]).attr('data-y', d[0][1]);
                                return xScale(d[i][0]);
                            } else {
                                overlay.attr('data-x', '').attr('data-y', '');
                                return 0;
                            }
                        }).attr('cy', function (d, i) {
                            if (d && d[i]) {
                                return yScale(d[i][1]);
                            } else {
                                return 0;
                            }
                        }).attr('fill', function (d, i) {
                            if (d && d[i]) {
                                return '#787878';
                            } else {
                                return 'none';
                            }
                        });

                        tipline.attr('stroke', '#909090').attr('opacity', 1);
                        if (dot_arr && dot_arr[0]) {
                            tipg.attr('transform', 'translate(' + (xScale(dot_arr[0][0]) + defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')');
                        } else {
                            tipg.attr('transform', 'translate(' + (-2) + ',' + (-2) + ')');
                        }
                    } else {
                        for (var bi = 0; bi < len_ab; bi++) {
                            tipdot.append('circle')
                                .attr('r', 2.5)
                                .attr('cx', 0)
                                .attr('cy', 0)
                                .attr('fill', '#787878');
                        }
                    }
                }

                if (defaults.tip.show) {
                    var info = '';
                    if (dot_arr.length > 0) {
                        if (Object.prototype.toString.call(defaults.tip.ytag) === '[object Array]') {
                            for (var di = 0, len_di = dot_arr.length; di < len_di; di++) {
                                if (di == 0 && dot_arr[di][0]) {
                                    info += defaults.tip.xtag + dot_arr[di][0] + '<br>';
                                }
                                if(dot_arr[di][1]){
                                    info += defaults.tip.ytag[di] + dot_arr[di][1] + '<br>';
                                }
                            }
                        }
                    }
                    self.showTip(true, d3.event, this, defaults.tip, defaults.layout.margin, info);
                }
            });

            overlay.on('mouseout', function () {
                var dots = tipdot.selectAll('circle');
                if (dots._groups[0].length > 0) {
                    dots.attr('fill', 'none');
                }
                tipline.attr('stroke', 'none');

                if (defaults.tip.show) {
                    self.showTip(false);
                }
            });
        }
        /*--------- 添加鼠标遮盖范围 - end ---------*/

        return true;
    },


    /**
     * 画线段散点图 x 轴为数值型
     * 拷贝至 dogLeg
     * @param config
     * @returns {boolean}
     */
    segment: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#04adee'],              // 折线颜色
            xAxis: {                         // x轴
                data: [],                    // x轴数据
                ticks: 0,                    // x轴刻度数
                index: [],                   // x轴索引
                render: '',                  // 渲染回调函数
                show: true,                  // 是否显示(默认true)
                orient: 'bottom',            // x轴方向(默认bottom)
                sort: 'asc'                  // 刻度排序(默认上升asc)
            },
            yAxis: {                         // y轴
                data: [],
                ticks: 0,
                index: [],
                render: '',
                show: true,
                orient: 'left',
                sort: 'asc'
            },
            data: [],                         // 原始数据集
            layout: {
                xtag: 'x轴',                  // x轴显示文本
                ytag: 'y轴',                  // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                            // 距容器边距
                xgrid: false,                 // x轴网格
                ygrid: false                  // y轴网格
            },
            areaShow: false,                  // 是否显示区间背景(默认false不显示)
            area: [],                         // 区间背景
            pointText: {
                show: false,                  // 节点文字是否显示(默认false不显示)
                render: '',                   // 渲染回调函数
                circle: false,                // 节点圆圈是否显示(默认false不显示)
                startShow: false,             // 显示折线开始节点圆圈(默认false不显示)
                stopShow: false               // 显示折线结束节点圆圈(默认false不显示)
            },
            tip: {
                show: false,
                xtag: 'x轴',
                ytag: 'y轴'
            }
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('area')) {
                    defaults.area = config['area'];
                }

                if (config.hasOwnProperty('areaShow')) {
                    defaults.areaShow = config['areaShow'];
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('index')) {
                        defaults.xAxis.index = config['xAxis']['index'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('orient')) {
                        defaults.xAxis.orient = config['xAxis']['orient'];
                    }
                    if (config['xAxis'].hasOwnProperty('sort')) {
                        defaults.xAxis.sort = config['xAxis']['sort'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('index')) {
                        defaults.yAxis.index = config['yAxis']['index'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('orient')) {
                        defaults.yAxis.orient = config['yAxis']['orient'];
                    }
                    if (config['yAxis'].hasOwnProperty('sort')) {
                        defaults.yAxis.sort = config['yAxis']['sort'];
                    }
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.render = config['pointText']['render'];
                    }
                    if (config['pointText'].hasOwnProperty('circle')) {
                        defaults.pointText.circle = config['pointText']['circle'];
                    }
                    if (config['pointText'].hasOwnProperty('startShow')) {
                        defaults.pointText.startShow = config['pointText']['startShow'];
                    }
                    if (config['pointText'].hasOwnProperty('stopShow')) {
                        defaults.pointText.stopShow = config['pointText']['stopShow'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var width = this.area(defaults.container).width;
        var height = this.area(defaults.container).height;

        // get axis data
        var axisData = defaults.data;

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x.data;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y.data;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.x.ticks;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.y.ticks;
        }

        // set axis index
        if (defaults.xAxis.index.length === 0) {
            defaults.xAxis.index = axisData.x.index;
        }

        if (defaults.yAxis.index.length === 0) {
            defaults.yAxis.index = axisData.y.index;
        }

        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale
        var xScale;
        if (defaults.xAxis.sort === 'asc') {
            xScale = d3.scaleLinear()
                .domain([d3.min(defaults.xAxis.data), d3.max(defaults.xAxis.data)])
                .range([0, width - defaults.layout.margin.left - defaults.layout.margin.right])
                .nice();
        } else if (defaults.xAxis.sort === 'desc') {
            xScale = d3.scaleLinear()
                .domain([d3.min(defaults.xAxis.data), d3.max(defaults.xAxis.data)])
                .range([width - defaults.layout.margin.left - defaults.layout.margin.right, 0])
                .nice();
        }

        // yScale
        var yScale;
        if (defaults.yAxis.sort === 'asc') {
            yScale = d3.scaleLinear()
                .domain([d3.min(defaults.yAxis.data), d3.max(defaults.yAxis.data)])
                .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
                .nice();
        } else if (defaults.yAxis.sort === 'desc') {
            yScale = d3.scaleLinear()
                .domain([d3.max(defaults.yAxis.data), d3.min(defaults.yAxis.data)])
                .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
                .nice();
        }

        // xAxis
        var xAxis;
        if (defaults.xAxis.orient === 'bottom') {
            if (defaults.xAxis.ticks === Infinity) {
                xAxis = d3.axisBottom(xScale);
            } else {
                xAxis = d3.axisBottom(xScale)
                    .ticks(defaults.xAxis.ticks);
            }
        } else if (defaults.xAxis.orient === 'top') {
            if (defaults.xAxis.ticks === Infinity) {
                xAxis = d3.axisTop(xScale)
            } else {
                xAxis = d3.axisTop(xScale)
                    .ticks(defaults.xAxis.ticks);
            }
        }

        // yAxis
        var yAxis;
        if (defaults.yAxis.orient === 'left') {
            if (defaults.yAxis.ticks === Infinity) {
                yAxis = d3.axisLeft(yScale);
            } else {
                yAxis = d3.axisLeft(yScale)
                    .ticks(defaults.yAxis.ticks);
            }
        } else if (defaults.yAxis.orient === 'right') {
            if (defaults.yAxis.ticks === Infinity) {
                yAxis = d3.axisRight(yScale);
            } else {
                yAxis = d3.axisRight(yScale)
                    .ticks(defaults.yAxis.ticks);
            }
        }

        // xGrid
        var xGrid;
        if (defaults.xAxis.orient === 'bottom') {
            if (defaults.xAxis.ticks === Infinity) {
                xGrid = d3.axisBottom(xScale)
                    .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom]);
            } else {
                xGrid = d3.axisBottom(xScale)
                    .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom])
                    .ticks(defaults.xAxis.ticks);
            }
        } else if (defaults.xAxis.orient === 'top') {
            if (defaults.xAxis.ticks === Infinity) {
                xGrid = d3.axisTop(xScale)
                    .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom]);
            } else {
                xGrid = d3.axisTop(xScale)
                    .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom])
                    .ticks(defaults.xAxis.ticks);
            }
        }

        // yGrid
        var yGrid;
        if (defaults.yAxis.orient === 'left') {
            if (defaults.yAxis.ticks === Infinity) {
                yGrid = d3.axisRight(yScale)
                    .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right]);
            } else {
                yGrid = d3.axisRight(yScale)
                    .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right])
                    .ticks(defaults.yAxis.ticks);
            }
        } else if (defaults.yAxis.orient === 'right') {
            if (defaults.yAxis.ticks === Infinity) {
                yGrid = d3.axisLeft(yScale)
                    .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right]);
            } else {
                yGrid = d3.axisLeft(yScale)
                    .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right])
                    .ticks(defaults.yAxis.ticks);
            }
        }


        /*--------- 添加区间背景 - start ---------*/
        if (defaults.areaShow) {
            var lens = defaults.area.length;
            var bg_w = 0, bg_h = 0, bg_y = 0;
            if (lens > 0) {
                for (var n = 0; n < lens; n++) {
                    bg_w = width - defaults.layout.margin.left - defaults.layout.margin.right;
                    bg_h = (yScale(defaults.area[n].range[1]) - yScale(defaults.area[n].range[0]));
                    bg_h = bg_h < 0 ? bg_h * (-1) : bg_h;
                    bg_y = (yScale(defaults.area[n].range[1]) + defaults.layout.margin.top);

                    svg.append('g')
                        .attr('class', 'zy-area-bg')
                        .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + bg_y + ')')
                        .append('rect')
                        .attr('width', bg_w)
                        .attr('height', bg_h)
                        .attr('opacity', 0.8)
                        .attr('fill', defaults.area[n].background);

                    if (defaults.area[n].text) {
                        svg.append('g')
                            .attr('class', 'zy-area-text')
                            .attr('transform', 'translate(' + (width - defaults.layout.margin.right / 2) + ',' + (bg_y + 12) + ')')
                            .selectAll('text')
                            .data(defaults.area[n].text)
                            .enter()
                            .append('text')
                            .text(function (d) {
                                return d;
                            })
                            .attr('font-size', d3Config.axisFontSize)
                            .attr('fill', d3Config.axisColor)
                            .attr('y', function (d, i) {
                                return i * 12;
                            });
                    }
                }
            } else {
                bg_w = width - defaults.layout.margin.left - defaults.layout.margin.right;
                bg_h = (yScale(d3.max(defaults.yAxis.data)) - yScale(d3.min(defaults.yAxis.data)));
                bg_h = bg_h < 0 ? bg_h * (-1) : bg_h;
                bg_y = (yScale(d3.max(defaults.yAxis.data)) + defaults.layout.margin.top);

                svg.append('g')
                    .attr('class', 'zy-area-bg')
                    .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + bg_y + ')')
                    .append('rect')
                    .attr('width', bg_w)
                    .attr('height', bg_h)
                    .attr('opacity', 0.8)
                    .attr('fill', d3Config.areaBgColor);
            }
        }
        /*--------- 添加区间背景 - end ---------*/


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var x_xg = 0, y_xg = 0;
            if (defaults.xAxis.orient === 'bottom') {
                x_xg = defaults.layout.margin.left;
                y_xg = defaults.layout.margin.top;
            } else if (defaults.xAxis.orient === 'top') {
                x_xg = defaults.layout.margin.left;
                y_xg = height - defaults.layout.margin.top;
            }
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + x_xg + ',' + y_xg + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var x_yg = 0, y_yg = 0;
            if (defaults.yAxis.orient === 'left') {
                x_yg = defaults.layout.margin.left;
                y_yg = defaults.layout.margin.top;
            } else if (defaults.yAxis.orient === 'right') {
                x_yg = width - defaults.layout.margin.left;
                y_yg = defaults.layout.margin.top;
            }
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + x_yg + ',' + y_yg + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var x_xa = 0, y_xa = 0;
            if (defaults.xAxis.orient === 'bottom') {
                x_xa = defaults.layout.margin.left;
                y_xa = height - defaults.layout.margin.bottom;
            } else if (defaults.xAxis.orient === 'top') {
                x_xa = defaults.layout.margin.left;
                y_xa = defaults.layout.margin.top;
            }
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + x_xa + ',' + y_xa + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .text(function (d) {
                    if (defaults.xAxis.render instanceof Function) {
                        return defaults.xAxis.render(d);
                    } else {
                        return d;
                    }
                })
                .attr('font-size', d3Config.axisFontSize)
                .attr('fill', d3Config.axisColor);

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

        }

        if (defaults.yAxis.show) {
            var x_ya = 0, y_ya = 0;
            if (defaults.yAxis.orient === 'left') {
                x_ya = defaults.layout.margin.left;
                y_ya = defaults.layout.margin.top;
            } else if (defaults.yAxis.orient === 'right') {
                x_ya = width - defaults.layout.margin.left;
                y_ya = defaults.layout.margin.top;
            }
            var yaxis = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + x_ya + ',' + y_ya + ')')
                .call(yAxis);

            yaxis.selectAll('text')
                .text(function (d) {
                    if (defaults.yAxis.render instanceof Function) {
                        return defaults.yAxis.render(d);
                    } else {
                        return d;
                    }
                })
                .attr('font-size', d3Config.axisFontSize)
                .attr('fill', d3Config.axisColor);

            yaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            var x_xt = 0, y_xt = 0;
            if (defaults.xAxis.orient === 'bottom') {
                x_xt = width / 2;
                y_xt = height - defaults.layout.margin.bottom / 10;
            } else if (defaults.xAxis.orient === 'top') {
                x_xt = width - defaults.layout.margin.right * 3;
                y_xt = defaults.layout.margin.top / 3;
            }
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + x_xt + ',' + y_xt + ')')
                .append('text')
                .text(defaults.layout.xtag)
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);
        }

        if (defaults.layout.ytag) {
            var x_yt = 0, y_yt = 0;
            if (defaults.yAxis.orient === 'left') {
                if (defaults.xAxis.orient === 'bottom') {
                    x_yt = 0;
                    y_yt = defaults.layout.margin.top - 10;
                } else if (defaults.xAxis.orient === 'top') {
                    x_yt = 0;
                    y_yt = height - defaults.layout.margin.bottom / 3;
                }
            } else if (defaults.yAxis.orient === 'right') {
                x_yt = width - defaults.layout.margin.right;
                y_yt = height - defaults.layout.margin.bottom / 3;
            }
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + x_yt + ',' + y_yt + ')')
                .append('text')
                .text(defaults.layout.ytag)
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加折线 - start ---------*/
        var line = d3.line()
            .x(function (d) {
                return xScale(d[0]);
            })
            .y(function (d) {
                return yScale(d[1]);
            });
        // 单条
        if (defaults.data.store.length > 0) {
            for (var i = 0, len = defaults.data.store.length; i < len; i++) {
                svg.append('path')
                    .attr('class', 'zy-line-path')
                    .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                    .attr('d', line(defaults.data.store[i]))
                    .attr('stroke', defaults.color[0])
                    .attr('fill', 'none')
                    .attr('stroke-width', d3Config.lineWidth)
                    .attr('shape-rendering', d3Config.lineEdges);
            }
        }
        /*--------- 添加折线 - end ---------*/

        /*--------- 添加圆圈 - start ---------*/
        if (defaults.pointText.circle) {
            // 单组
            if (defaults.data.store.length > 0) {
                for (var j = 0, len_j = defaults.data.store.length; j < len_j; j++) {
                    svg.append('g')
                        .attr('class', 'zy-circle')
                        .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                        .selectAll('circle')
                        .data(defaults.data.store[j])
                        .enter()
                        .append('circle')
                        .attr('cx', line.x())
                        .attr('cy', line.y())
                        .attr('r', 3)
                        .attr('stroke', defaults.color[0])
                        .attr('fill', d3Config.circleFillColor)
                        .attr('stroke-width', d3Config.circleBorder)
                        .attr('data-x', function (d) {
                            return d[0];
                        })
                        .attr('data-y', function (d) {
                            if(defaults.yAxis.render instanceof Function){
                                return defaults.yAxis.render(d[1]);
                            }else{
                                return d[1];
                            }
                        })
                        .on('mouseover', function () {
                            d3.select(this)
                                .attr('r', 4);

                            if (defaults.tip.show) {
                                self.showTip(true, d3.event, this, defaults.tip, defaults.layout.margin);
                            }
                        })
                        .on('mouseout', function () {
                            d3.select(this)
                                .attr('r', 3);

                            if (defaults.tip.show) {
                                self.showTip(false);
                            }
                        });
                }
            }
        }
        /*--------- 添加圆圈 - end ---------*/

        return true;
    },


    /**
     * 画散点图 x 轴为数值型
     * @param config
     * @returns {boolean}
     */
    point: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#02aeee'],              // 散点颜色
            tip: {                           // 显示提示
                show: true,
                xtag: 'x值',
                ytag: 'y值'
            },
            xAxis: {                         // x轴数据
                data: [],
                ticks: 0,
                index: [],
                show: true,
                render: ''
            },
            yAxis: {                         // y轴数据
                data: [],
                ticks: 0,
                index: [],
                show: true,
                render: ''
            },
            data: [],                        // 原始数据集
            layout: {
                xtag: 'x轴',                 // x轴显示文本
                ytag: 'y轴',                 // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                           // 距容器边距
                xgrid: true,                 // x轴网格
                ygrid: true                  // y轴网格
            },
            areaShow: false,                 // 是否显示区间背景(默认false不显示)
            area: [],                        // 背景区域
            pointText: {
                show: false,
                render: ''
            },
            circleRender: ''                 // 散点颜色渲染
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('area')) {
                    defaults.area = config['area'];
                }

                if (config.hasOwnProperty('areaShow')) {
                    defaults.areaShow = config['areaShow'];
                }

                if (config.hasOwnProperty('circleRender')) {
                    defaults.circleRender = config['circleRender'];
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.render = config['pointText']['render'];
                    }
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('index')) {
                        defaults.xAxis.index = config['xAxis']['index'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('index')) {
                        defaults.yAxis.index = config['yAxis']['index'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var area = this.area(defaults.container);
        var width = area.width;
        var height = area.height;

        // get axis data
        var axisData = this.axisData(defaults.data);

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x.data;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y.data;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.x.ticks;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.y.ticks;
        }

        // set axis index
        if (defaults.xAxis.index.length === 0) {
            defaults.xAxis.index = axisData.x.index;
        }

        if (defaults.yAxis.index.length === 0) {
            defaults.yAxis.index = axisData.y.index;
        }


        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale
        var xScale = d3.scaleLinear()
            .domain([d3.min(defaults.xAxis.data), d3.max(defaults.xAxis.data)])
            .range([0, width - defaults.layout.margin.left - defaults.layout.margin.right])
            .nice();

        // yScale
        var yScale = d3.scaleLinear()
            .domain([d3.min(defaults.yAxis.data), d3.max(defaults.yAxis.data)])
            .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
            .nice();

        // xAxis
        var xAxis = d3.axisBottom(xScale);
        if (defaults.xAxis.ticks !== Infinity) {
            xAxis.ticks(defaults.xAxis.ticks)
        }

        // yAxis
        var yAxis = d3.axisLeft(yScale);
        if (defaults.yAxis.ticks !== Infinity) {
            yAxis.ticks(defaults.yAxis.ticks)
        }

        // xGrid
        var xGrid = d3.axisBottom(xScale)
            .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom]);
        if (defaults.xAxis.ticks !== Infinity) {
            xGrid.ticks(defaults.xAxis.ticks)
        }

        // yGrid
        var yGrid = d3.axisRight(yScale)
            .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right]);
        if (defaults.yAxis.ticks !== Infinity) {
            yGrid.ticks(defaults.yAxis.ticks)
        }


        /*--------- 添加区间背景 - start ---------*/
        if (defaults.areaShow) {
            var lens = defaults.area.length;
            var bg_w = 0, bg_h = 0, bg_y = 0;
            if (lens > 0) {
                for (var n = 0; n < lens; n++) {
                    bg_w = width - defaults.layout.margin.left - defaults.layout.margin.right;
                    bg_h = (yScale(defaults.area[n].range[1]) - yScale(defaults.area[n].range[0]));
                    bg_h = bg_h < 0 ? bg_h * (-1) : bg_h;
                    bg_y = (yScale(defaults.area[n].range[1]) + defaults.layout.margin.top);

                    svg.append('g')
                        .attr('class', 'zy-area-bg')
                        .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + bg_y + ')')
                        .append('rect')
                        .attr('width', bg_w)
                        .attr('height', bg_h)
                        .attr('opacity', 0.8)
                        .attr('fill', defaults.area[n].background);
                }
            } else {
                bg_w = width - defaults.layout.margin.left - defaults.layout.margin.right;
                bg_h = height - defaults.layout.margin.top - defaults.layout.margin.bottom;

                svg.append('g')
                    .attr('class', 'zy-area-bg')
                    .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
                    .append('rect')
                    .attr('width', bg_w)
                    .attr('height', bg_h)
                    .attr('opacity', 0.8)
                    .attr('fill', d3Config.areaBgColor);
            }
        }
        /*--------- 添加区间背景 - end ---------*/


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + (height - defaults.layout.margin.bottom) + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.yAxis.show) {
            var yaxis = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yAxis);

            yaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            yaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + (width / 2) + ',' + (height - defaults.layout.margin.bottom / 10) + ')')
                .append('text')
                .text(defaults.layout.xtag)
                .attr('font-size', d3Config.axisFontSize)
                .attr('fill', d3Config.axisColor);
        }

        if (defaults.layout.ytag) {
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + (0) + ',' + (defaults.layout.margin.top / 2) + ')')
                .append('text')
                .text(defaults.layout.ytag)
                .attr('font-size', d3Config.axisFontSize)
                .attr('fill', d3Config.axisColor);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加散点 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-point-circle')
            .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
            .selectAll('circle')
            .data(defaults.data)
            .enter()
            .append('circle')
            .attr('cx', function (d) {
                return xScale(d.x);
            })
            .attr('cy', function (d) {
                return yScale(d.y);
            })
            .attr('r', 0.5)
            .attr('opacity', function (d) {
                if (d.hasOwnProperty('stop')) {
                    return 0;
                }
                return 0.7;
            })
            .attr('data-x', function (d) {
                return d.x;
            })
            .attr('data-y', function (d) {
                return d.y;
            })
            .on('mouseover', function () {
                d3.select(this)
                    .attr('r', 7.5);

                if (defaults.tip.show) {
                    self.showTip(true, d3.event, this, defaults.tip, defaults.layout.margin);
                }
            })
            .on('mouseout', function () {
                d3.select(this)
                    .attr('r', 5.5);

                if (defaults.tip.show) {
                    self.showTip(false);
                }
            })
            .transition()
            .duration(300)
            .attr('r', 5.5)
            .style('fill', function (d) {
                if (defaults.circleRender instanceof Function) {
                    return defaults.circleRender(d);
                } else {
                    return defaults.color[0];
                }
            })
            .delay(function (d, i) {
                return 10 * i;
            });
        /*--------- 添加散点 - end ---------*/

        return true;
    },


    /**
     * 以 y 轴为时间的 散点图
     * 注意 此用在时钟分布图
     * 注意 此时间用的的 UTC 时间
     * @param config
     * @returns {boolean}
     */
    pointClock: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#02aeee'],              // 散点颜色
            tip: {                           // 显示提示
                show: true,
                xtag: 'x值',
                ytag: 'y值'
            },
            xAxis: {                         // x轴数据
                data: [],
                ticks: 0,
                index: [],
                show: true,
                render: ''
            },
            yAxis: {                         // y轴数据
                data: [],
                ticks: 0,
                index: [],
                show: true,
                render: ''
            },
            data: [],                        // 原始数据集
            layout: {
                xtag: 'x轴',                 // x轴显示文本
                ytag: 'y轴',                 // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                           // 距容器边距
                xgrid: true,                 // x轴网格
                ygrid: true                  // y轴网格
            },
            areaShow: false,                 // 是否显示区间背景(默认false不显示)
            area: [],                        // 背景区域
            pointText: {
                show: false,
                render: ''
            },
            circleRender: ''                 // 散点颜色渲染
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('circleRender')) {
                    defaults.circleRender = config['circleRender'];
                }

                if (config.hasOwnProperty('area')) {
                    defaults.area = config['area'];
                }

                if (config.hasOwnProperty('areaShow')) {
                    defaults.areaShow = config['areaShow'];
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.render = config['pointText']['render'];
                    }
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('index')) {
                        defaults.xAxis.index = config['xAxis']['index'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('index')) {
                        defaults.yAxis.index = config['yAxis']['index'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var area = this.area(defaults.container);
        var width = area.width;
        var height = area.height;

        // get axis data
        var axisData = this.axisData(defaults.data);

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x.data;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y.data;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.x.ticks;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.y.ticks;
        }

        // set axis index
        if (defaults.xAxis.index.length === 0) {
            defaults.xAxis.index = axisData.x.index;
        }

        if (defaults.yAxis.index.length === 0) {
            defaults.yAxis.index = axisData.y.index;
        }


        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale
        var xScale = d3.scaleLinear()
            .domain([d3.min(defaults.xAxis.data), d3.max(defaults.xAxis.data)])
            .range([0, width - defaults.layout.margin.left - defaults.layout.margin.right])
            .nice();

        var yScale = d3.scaleUtc()
            .domain([d3.min(defaults.yAxis.data), d3.max(defaults.yAxis.data)])
            .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
            .nice();

        // xAxis
        var xAxis = d3.axisBottom(xScale)
            .ticks(defaults.xAxis.ticks);

        // yAxis
        var yAxis = d3.axisLeft(yScale)
            .ticks(defaults.yAxis.ticks);

        // xGrid
        var xGrid = d3.axisBottom(xScale)
            .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom])
            .ticks(defaults.xAxis.ticks);

        // yGrid
        var yGrid = d3.axisRight(yScale)
            .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right])
            .ticks(defaults.yAxis.ticks);


        /*--------- 添加区间背景 - start ---------*/
        if (defaults.areaShow) {
            var lens = defaults.area.length;
            var bg_w = 0, bg_h = 0, bg_y = 0;
            if (lens > 0) {
                for (var n = 0; n < lens; n++) {
                    bg_w = width - defaults.layout.margin.left - defaults.layout.margin.right;
                    bg_h = (yScale(defaults.area[n].range[1]) - yScale(defaults.area[n].range[0]));
                    bg_h = bg_h < 0 ? bg_h * (-1) : bg_h;
                    bg_y = (yScale(defaults.area[n].range[1]) + defaults.layout.margin.top);

                    svg.append('g')
                        .attr('class', 'zy-area-bg')
                        .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + bg_y + ')')
                        .append('rect')
                        .attr('width', bg_w)
                        .attr('height', bg_h)
                        .attr('opacity', 0.8)
                        .attr('fill', defaults.area[n].background);
                }
            } else {
                bg_w = width - defaults.layout.margin.left - defaults.layout.margin.right;
                bg_h = height - defaults.layout.margin.top - defaults.layout.margin.bottom;

                svg.append('g')
                    .attr('class', 'zy-area-bg')
                    .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
                    .append('rect')
                    .attr('width', bg_w)
                    .attr('height', bg_h)
                    .attr('opacity', 0.8)
                    .attr('fill', d3Config.areaBgColor);
            }
        }
        /*--------- 添加区间背景 - end ---------*/


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + (height - defaults.layout.margin.bottom) + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.yAxis.show) {
            var yaxis = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yAxis);

            yaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize)
                .text(function (d) {
                    if (defaults.yAxis.render instanceof Function) {
                        return defaults.yAxis.render(d);
                    } else {
                        return d;
                    }
                });

            yaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + (width / 2) + ',' + (height - defaults.layout.margin.bottom / 10) + ')')
                .append('text')
                .text(defaults.layout.xtag)
                .attr('font-size', d3Config.axisFontSize)
                .attr('fill', d3Config.axisColor);
        }

        if (defaults.layout.ytag) {
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + (0) + ',' + (defaults.layout.margin.top / 2) + ')')
                .append('text')
                .text(defaults.layout.ytag)
                .attr('font-size', d3Config.axisFontSize)
                .attr('fill', d3Config.axisColor);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加散点 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-point-circle')
            .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
            .selectAll('circle')
            .data(defaults.data)
            .enter()
            .append('circle')
            .attr('cx', function (d) {
                return xScale(d.x);
            })
            .attr('cy', function (d) {
                return yScale(d.y);
            })
            .attr('r', 0.5)
            .attr('opacity', function (d) {
                if (d.hasOwnProperty('stop')) {
                    return 0;
                }
                return 0.7;
            })
            .attr('data-x', function (d) {
                return d.x;
            })
            .attr('data-y', function (d) {
                var temp_h = d.y.getUTCHours() < 10 ? '0' + d.y.getUTCHours().toString() : d.y.getUTCHours().toString();
                var temp_m = d.y.getUTCMinutes() < 10 ? '0' + d.y.getUTCMinutes().toString() : d.y.getUTCMinutes().toString();
                return temp_h + ':' + temp_m;
            })
            .on('mouseover', function () {
                d3.select(this)
                    .attr('r', 7.5);

                if (defaults.tip.show) {
                    self.showTip(true, d3.event, this, defaults.tip);
                }
            })
            .on('mouseout', function () {
                d3.select(this)
                    .attr('r', 5.5);

                if (defaults.tip.show) {
                    self.showTip(false);
                }
            })
            .transition()
            .duration(300)
            .attr('r', 5.5)
            .style('fill', function (d) {
                if (defaults.circleRender instanceof Function) {
                    return defaults.circleRender(d);
                } else {
                    return defaults.color[0];
                }
            })
            .delay(function (d, i) {
                return 10 * i;
            });
        /*--------- 添加散点 - end ---------*/

        /* 附加值情况 */
        // 将 x 轴 ticks 返回回去
        var temp_dom = document.getElementById(defaults.container);
        var temp_str = '';
        var texts = xaxis.selectAll('text')._groups[0];
        for (var u = 0, len_u = texts.length; u < len_u; u++) {
            var temp_text = texts[u].textContent;
            temp_text = temp_text.replace instanceof Function ? temp_text.replace(',', '') : '';
            if (u === len_u - 1) {
                temp_str += temp_text;
            } else {
                temp_str += temp_text + ',';
            }
            temp_dom.setAttribute('data-str', temp_str);
        }

        return true;
    },


    /**
     * 画折线图 x 轴为序数值
     * @param config
     * @returns {boolean}
     */
    ordinal: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#61ade9'],              // 折线颜色
            xAxis: {                         // x轴数据
                data: [],
                ticks: 0,
                index: [],
                show: true,
                render: ''
            },
            yAxis: {                         // y轴数据
                data: [],
                ticks: 0,
                index: [],
                show: true,
                render: ''
            },
            store: [],                       // 格式化后的数据
            data: [],                        // 原始数据集
            layout: {
                xtag: 'x轴',                 // x轴显示文本
                ytag: 'y轴',                 // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                           // 距容器边距
                xgrid: false,                // x轴网格
                ygrid: false                 // y轴网格
            },
            areaShow: false,                 // 是否显示区间背景(默认false不显示)
            area: [],                        // 区间背景
            pointText: {
                show: false,                 // 节点文字是否显示(默认true显示)
                render: '',                  // 渲染回调函数
                circle: false
            },
            tip: {
                show: false,
                xtag: 'x轴',
                ytag: 'y轴'
            }
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('area')) {
                    defaults.area = config['area'];
                }

                if (config.hasOwnProperty('areaShow')) {
                    defaults.areaShow = config['areaShow'];
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.render = config['pointText']['render'];
                    }
                    if (config['pointText'].hasOwnProperty('circle')) {
                        defaults.pointText.circle = config['pointText']['circle'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('index')) {
                        defaults.xAxis.index = config['xAxis']['index'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('index')) {
                        defaults.yAxis.index = config['yAxis']['index'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var area = this.area(defaults.container);
        var width = area.width;
        var height = area.height;

        // get axis data
        var axisData = this.axisData(defaults.data);

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x.data;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y.data;
        }

        if (defaults.store.length === 0) {
            defaults.store = axisData.store;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.x.ticks;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.y.ticks;
        }

        // set axis index
        if (defaults.xAxis.index.length === 0) {
            defaults.xAxis.index = axisData.x.index;
        }

        if (defaults.yAxis.index.length === 0) {
            defaults.yAxis.index = axisData.y.index;
        }

        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale - ordinal
        var xScale_ord = d3.scaleOrdinal()
            .domain(defaults.xAxis.index)
            .range(defaults.xAxis.data);

        // yScale - ordinal
        var yScale_ord = d3.scaleOrdinal()
            .domain(defaults.yAxis.index)
            .range(defaults.yAxis.data);

        // xScale
        var xScale, xScale_liner;
        if (defaults.xAxis.index.length >= 10) {
            xScale = d3.scaleLinear()
                .domain([d3.min(defaults.xAxis.index), d3.max(defaults.xAxis.index)])
                .range([0, (width - defaults.layout.margin.left - defaults.layout.margin.right)])
                .nice();
        } else {
            xScale = d3.scaleBand()
                .domain(defaults.xAxis.index)
                .range([0, (width - defaults.layout.margin.left - defaults.layout.margin.right)])
                .paddingInner(1);

            xScale_liner = d3.scaleLinear()
                .domain([d3.min(defaults.xAxis.index), d3.max(defaults.xAxis.index)])
                .range([0, (width - defaults.layout.margin.left - defaults.layout.margin.right)])
                .nice();
        }
        // yScale
        var yScale = d3.scaleLinear()
            .domain([d3.min(defaults.yAxis.data), d3.max(defaults.yAxis.data)])
            .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
            .nice();

        // xAxis
        var xAxis = d3.axisBottom(xScale);
        if (defaults.xAxis.ticks !== Infinity) {
            xAxis.ticks(defaults.xAxis.ticks);
        } else {
            if (axisData.x.ticks < 10) {
                xAxis.ticks(axisData.x.ticks);
            }
        }

        // yAxis
        var yAxis = d3.axisLeft(yScale);
        if (defaults.xAxis.ticks !== Infinity) {
            yAxis.ticks(defaults.yAxis.ticks);
        }

        // xGrid
        var xGrid = d3.axisBottom(xScale)
            .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom]);
        if (defaults.xAxis.ticks !== Infinity) {
            xGrid.ticks(defaults.xAxis.ticks);
        } else {
            if (axisData.x.ticks < 10) {
                xGrid.ticks(axisData.x.ticks);
            }
        }

        // yGrid
        var yGrid = d3.axisRight(yScale)
            .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right]);
        if (defaults.yAxis.ticks !== Infinity) {
            yGrid.ticks(defaults.yAxis.ticks);
        }


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加区间背景 - start ---------*/
        if (defaults.areaShow) {
            var lens = defaults.area.length;
            var bg_w = 0, bg_h = 0, bg_y;
            if (lens > 0) {
                for (var n = 0; n < lens; n++) {
                    bg_w = width - defaults.layout.margin.left - defaults.layout.margin.right;
                    if (defaults.area[n].range[1]) {
                        bg_h = (yScale(defaults.area[n].range[1]) - yScale(defaults.area[n].range[0]));
                    } else {
                        bg_h = 1;
                    }
                    bg_h = bg_h < 0 ? bg_h * (-1) : bg_h;
                    if (defaults.area[n].range[1]) {
                        bg_y = (yScale(defaults.area[n].range[1]) + defaults.layout.margin.top);
                    } else {
                        bg_y = (yScale(defaults.area[n].range[0]) + defaults.layout.margin.top);
                    }

                    bg_y = parseInt(bg_y);

                    if (bg_y > 0) {
                        svg.append('g')
                            .attr('class', 'zy-area-bg')
                            .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (bg_y) + ')')
                            .append('rect')
                            .attr('width', bg_w)
                            .attr('height', bg_h)
                            .attr('opacity', 0.8)
                            .attr('fill', defaults.area[n].background)
                            .attr('shape-rendering', 'crispEdges');
                    }

                    if (defaults.area[n].text) {
                        svg.append('g')
                            .attr('class', 'zy-area-text')
                            .attr('transform', 'translate(' + (width - defaults.layout.margin.right / 2) + ',' + (bg_y + 12) + ')')
                            .selectAll('text')
                            .data(defaults.area[n].text)
                            .enter()
                            .append('text')
                            .text(function (d) {
                                return d;
                            })
                            .attr('font-size', d3Config.axisFontSize)
                            .attr('fill', d3Config.axisColor)
                            .attr('y', function (d, i) {
                                return i * 12;
                            });
                    }
                }
            } else {
                bg_w = width - defaults.layout.margin.left - defaults.layout.margin.right;
                bg_h = height - defaults.layout.margin.top - defaults.layout.margin.bottom;

                svg.append('g')
                    .attr('class', 'zy-area-bg')
                    .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
                    .append('rect')
                    .attr('width', bg_w)
                    .attr('height', bg_h)
                    .attr('opacity', 0.8)
                    .attr('fill', d3Config.areaBgColor)
                    .attr('shape-rendering', 'crispEdges');
            }
        }
        /*--------- 添加区间背景 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + (height - defaults.layout.margin.bottom) + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .text(function (d) {
                    if (defaults.xAxis.render instanceof Function) {
                        return defaults.xAxis.render(xScale_ord(d));
                    } else {
                        if (d > d3.max(defaults.xAxis.index)) {
                            return '';
                        } else {
                            return xScale_ord(d);
                        }
                    }
                })
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.yAxis.show) {
            var yxais = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yAxis);

            yxais.selectAll('text')
                .text(function (d) {
                    if (defaults.yAxis.render instanceof Function) {
                        return defaults.yAxis.render(d);
                    } else {
                        return d;
                    }
                })
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            yxais.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yxais.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + (width / 2) + ',' + (height - defaults.layout.margin.bottom / 10) + ')')
                .append('text')
                .text(defaults.layout.xtag)
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);
        }

        if (defaults.layout.ytag) {
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + (0) + ',' + (defaults.layout.margin.top / 2) + ')')
                .append('text')
                .text(defaults.layout.ytag)
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加折线 - start ---------*/
        var temp = defaults.store[0];
        var line = d3.line()
            .x(function (d) {
                return xScale(d.index);
            })
            .y(function (d) {
                return yScale(d.y);
            });
        // 单条
        if (Object.prototype.toString.call(temp) === '[object Object]') {
            var path = svg.append('path')
                .attr('class', 'zy-line-path')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .attr('d', line(defaults.store))
                .attr('stroke', defaults.color[0])
                .attr('fill', 'none')
                .attr('stroke-width', d3Config.lineWidth)
                .attr('shape-rendering', d3Config.lineEdges);
        }
        // 多条
        if (Object.prototype.toString.call(temp) === '[object Array]') {
            for (var i = 0, len = defaults.data.length; i < len; i++) {
                var line_color = '#000000';
                if (defaults.color[i]) {
                    line_color = defaults.color[i];
                }
                var paths = svg.append('path')
                    .attr('class', 'zy-line-path')
                    .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                    .attr('d', line(defaults.store[i]))
                    .attr('stroke', line_color)
                    .attr('fill', 'none')
                    .attr('stroke-width', d3Config.lineWidth)
                    .attr('shape-rendering', d3Config.lineEdges);
            }
        }
        /*--------- 添加折线 - end ---------*/


        /*--------- 添加鼠标遮盖范围 - start ---------*/
        if (defaults.tip.show) {
            var tipg = svg.append('g')
                .attr('class', 'zy-overlay-tip')
                .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')');

            var tipline = tipg.append('line')
                .attr('y1', 0)
                .attr('y2', height - defaults.layout.margin.top - defaults.layout.margin.bottom)
                .attr('opacity', 0)
                .attr('stroke', '#909090')
                .attr('stroke-width', '1px')
                .attr('stroke-dasharray', '5,2')
                .attr('shape-rendering', 'crispEdges');

            var tipdot = svg.append('g')
                .attr('class', 'zy-overlay-dot')
                .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')');

            var overlay = svg.append('g')
                .attr('class', 'zy-overlay-rect')
                .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
                .append('rect')
                .attr('width', width - defaults.layout.margin.left)
                .attr('height', height - defaults.layout.margin.top - defaults.layout.margin.bottom)
                .attr('fill', 'none')
                .style('pointer-events', 'all');

            overlay.on('mousemove', function () {
                var pos = d3.mouse(this);
                var x = (xScale.invert) instanceof Function ? parseInt(xScale.invert(pos[0])) : parseInt(xScale_liner.invert(pos[0]));

                var dots = tipdot.selectAll('circle');

                if (defaults.store.length > 0) {
                    var len_ab = defaults.store.length;
                    var dot_arr = [];
                    for (var ai = 0; ai < len_ab; ai++) {
                        if (defaults.store[ai][x]) {
                            var index = defaults.store[ai][x]['index'];
                            var x_v = defaults.store[ai][x]['x'];
                            var y_v = defaults.store[ai][x]['y'];
                            dot_arr.push([x_v, y_v, index]);
                        }
                    }

                    if (dots._groups[0].length > 0) {
                        dots.datum(dot_arr).attr('cx', function (d, i) {
                            // append dom data for tip show
                            if (d && d[i]) {
                                overlay.attr('data-x', d[0][0]).attr('data-y', d[0][1]);
                                return xScale(d[i][2]);
                            } else {
                                overlay.attr('data-x', '').attr('data-y', '');
                                return 0;
                            }
                        }).attr('cy', function (d, i) {
                            if (d && d[i]) {
                                return yScale(d[i][1]);
                            } else {
                                return 0;
                            }
                        }).attr('fill', function (d, i) {
                            if (d && d[i]) {
                                return '#787878';
                            } else {
                                return 'none';
                            }
                        });

                        tipline.attr('stroke', '#909090').attr('opacity', 1);
                        if (dot_arr && dot_arr[0]) {
                            tipg.attr('transform', 'translate(' + (xScale(dot_arr[0][2]) + defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')');
                        } else {
                            tipg.attr('transform', 'translate(' + (0) + ',' + (0) + ')');
                        }
                    } else {
                        for (var bi = 0; bi < len_ab; bi++) {
                            tipdot.append('circle')
                                .attr('r', 2.5)
                                .attr('cx', 0)
                                .attr('cy', 0)
                                .attr('fill', '#787878');
                        }
                    }
                }

                if (defaults.tip.show) {
                    var info = '';
                    if (dot_arr.length > 0) {
                        if (Object.prototype.toString.call(defaults.tip.ytag) === '[object Array]') {
                            for (var di = 0, len_di = dot_arr.length; di < len_di; di++) {
                                if (di == 0) {
                                    info += defaults.tip.xtag + dot_arr[di][0] + '<br>';
                                }
                                info += defaults.tip.ytag[di] + dot_arr[di][1] + '<br>';
                            }
                        }
                    }
                    self.showTip(true, d3.event, this, defaults.tip, defaults.layout.margin, info);
                }
            });

            overlay.on('mouseout', function () {
                var dots = tipdot.selectAll('circle');
                if (dots._groups[0].length > 0) {
                    dots.attr('fill', 'none');
                }
                tipline.attr('stroke', 'none');

                if (defaults.tip.show) {
                    self.showTip(false);
                }
            });
        }
        /*--------- 添加鼠标遮盖范围 - end ---------*/

        return true;
    },


    /**
     * 画日期间隔 折线图 拷贝至 ordinal
     * @param config
     * @returns {boolean}
     */
    brand: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#61ade9'],              // 折线颜色
            xAxis: {                         // x轴数据
                data: [],
                ticks: 0,
                index: [],
                show: true,
                render: ''
            },
            yAxis: {                         // y轴数据
                data: [],
                ticks: 0,
                index: [],
                show: true,
                render: ''
            },
            store: [],                       // 格式化后的数据
            data: [],                        // 原始数据集
            layout: {
                xtag: 'x轴',                 // x轴显示文本
                ytag: 'y轴',                 // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                           // 距容器边距
                xgrid: false,                // x轴网格
                ygrid: false                 // y轴网格
            },
            areaShow: false,                 // 是否显示区间背景(默认false不显示)
            area: [],                        // 区间背景
            pointText: {
                show: false,                  // 节点文字是否显示(默认true显示)
                render: '',                  // 渲染回调函数
                circle: false
            },
            tip: {
                show: false,
                xtag: 'x轴',
                ytag: 'y轴'
            }
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('area')) {
                    defaults.area = config['area'];
                }

                if (config.hasOwnProperty('areaShow')) {
                    defaults.areaShow = config['areaShow'];
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.render = config['pointText']['render'];
                    }
                    if (config['pointText'].hasOwnProperty('circle')) {
                        defaults.pointText.circle = config['pointText']['circle'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('index')) {
                        defaults.xAxis.index = config['xAxis']['index'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('index')) {
                        defaults.yAxis.index = config['yAxis']['index'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var area = this.area(defaults.container);
        var width = area.width;
        var height = area.height;

        // get axis data
        var axisData = this.axisData(defaults.data);

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x.data;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y.data;
        }

        if (defaults.store.length === 0) {
            defaults.store = axisData.store;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.x.ticks;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.y.ticks;
        }

        // set axis index
        if (defaults.xAxis.index.length === 0) {
            defaults.xAxis.index = axisData.x.index;
        }

        if (defaults.yAxis.index.length === 0) {
            defaults.yAxis.index = axisData.y.index;
        }

        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale
        var xScale = d3.scaleBand()
            .domain(defaults.xAxis.data)
            .range([0, (width - defaults.layout.margin.left - defaults.layout.margin.right)])
            .paddingInner(1);

        // yScale
        var yScale = d3.scaleLinear()
            .domain([d3.min(defaults.yAxis.data), d3.max(defaults.yAxis.data)])
            .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
            .nice();

        // xAxis
        var xAxis = d3.axisBottom(xScale);
        if (defaults.xAxis.ticks !== Infinity) {
            xAxis.ticks(defaults.xAxis.ticks);
        }

        // yAxis
        var yAxis = d3.axisLeft(yScale);
        if (defaults.yAxis.ticks !== Infinity) {
            yAxis.ticks(defaults.yAxis.ticks)
        }

        // xGrid
        var xGrid = d3.axisBottom(xScale)
            .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom]);
        if (defaults.xAxis.ticks !== Infinity) {
            xGrid.ticks(defaults.xAxis.ticks)
        }

        // yGrid
        var yGrid = d3.axisRight(yScale)
            .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right]);
        if (defaults.yAxis.ticks !== Infinity) {
            yGrid.ticks(defaults.yAxis.ticks)
        }


        /*--------- 添加区间背景 - start ---------*/
        if (defaults.areaShow) {
            var lens = defaults.area.length;
            var bg_w = 0, bg_h = 0, bg_y;
            if (lens > 0) {
                for (var n = 0; n < lens; n++) {
                    bg_w = width - defaults.layout.margin.left - defaults.layout.margin.right;
                    if (defaults.area[n].range[1]) {
                        bg_h = (yScale(defaults.area[n].range[1]) - yScale(defaults.area[n].range[0]));
                    } else {
                        bg_h = 1.5;
                    }
                    bg_h = bg_h < 0 ? bg_h * (-1) : bg_h;
                    if (defaults.area[n].range[1]) {
                        bg_y = (yScale(defaults.area[n].range[1]) + defaults.layout.margin.top);
                    } else {
                        bg_y = (yScale(defaults.area[n].range[0]) + defaults.layout.margin.top);
                    }

                    if (bg_y > 0) {
                        svg.append('g')
                            .attr('class', 'zy-area-bg')
                            .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + bg_y + ')')
                            .append('rect')
                            .attr('width', bg_w)
                            .attr('height', bg_h)
                            .attr('opacity', 0.8)
                            .attr('fill', defaults.area[n].background);
                    }

                    if (defaults.area[n].text) {
                        svg.append('g')
                            .attr('class', 'zy-area-text')
                            .attr('transform', 'translate(' + (width - defaults.layout.margin.right / 2) + ',' + (bg_y + 12) + ')')
                            .selectAll('text')
                            .data(defaults.area[n].text)
                            .enter()
                            .append('text')
                            .text(function (d) {
                                return d;
                            })
                            .attr('font-size', d3Config.axisFontSize)
                            .attr('fill', d3Config.axisColor)
                            .attr('y', function (d, i) {
                                return i * 12;
                            });
                    }
                }
            } else {
                bg_w = width - defaults.layout.margin.left - defaults.layout.margin.right;
                bg_h = height - defaults.layout.margin.top - defaults.layout.margin.bottom;

                svg.append('g')
                    .attr('class', 'zy-area-bg')
                    .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                    .append('rect')
                    .attr('width', bg_w)
                    .attr('height', bg_h)
                    .attr('opacity', 0.8)
                    .attr('fill', d3Config.areaBgColor);
            }
        }
        /*--------- 添加区间背景 - end ---------*/


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + (height - defaults.layout.margin.bottom) + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .text(function (d) {
                    if (defaults.xAxis.render instanceof Function) {
                        return defaults.xAxis.render(d);
                    } else {
                        return d;
                    }
                })
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize)
                .attr('transform', function (d) {
                    if (defaults.xAxis.data.length > 20) {
                        return 'rotate(90),translate(30,-13)';
                    }
                    return 'rotate(0),translate(0,0)';
                });

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.yAxis.show) {
            var yxais = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yAxis);

            yxais.selectAll('text')
                .text(function (d) {
                    if (defaults.yAxis.render instanceof Function) {
                        return defaults.yAxis.render(d);
                    } else {
                        return d;
                    }
                })
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            yxais.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yxais.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + (width / 2) + ',' + (height - defaults.layout.margin.bottom / 6) + ')')
                .append('text')
                .text(defaults.layout.xtag)
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);
        }

        if (defaults.layout.ytag) {
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + (0) + ',' + (defaults.layout.margin.top / 2) + ')')
                .append('text')
                .text(defaults.layout.ytag)
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加折线 - start ---------*/
        var temp = defaults.store[0];
        var line = d3.line()
            .x(function (d) {
                return xScale(d.x);
            })
            .y(function (d) {
                return yScale(d.y);
            });
        // 单条
        if (Object.prototype.toString.call(temp) === '[object Object]') {
            var path = svg.append('path')
                .attr('class', 'zy-line-path')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .attr('d', line(defaults.store))
                .attr('stroke', defaults.color[0])
                .attr('fill', 'none')
                .attr('stroke-width', d3Config.lineWidth)
                .attr('shape-rendering', d3Config.lineEdges);
        }
        // 多条
        if (Object.prototype.toString.call(temp) === '[object Array]') {
            for (var i = 0, len = defaults.data.length; i < len; i++) {
                var line_color = '#000000';
                if (defaults.color[i]) {
                    line_color = defaults.color[i];
                }
                var paths = svg.append('path')
                    .attr('class', 'zy-line-path')
                    .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                    .attr('d', line(defaults.store[i]))
                    .attr('stroke', line_color)
                    .attr('fill', 'none')
                    .attr('stroke-width', d3Config.lineWidth)
                    .attr('shape-rendering', d3Config.lineEdges);
            }
        }
        /*--------- 添加折线 - end ---------*/


        /*--------- 添加圆圈 - start ---------*/
        // 单组
        if (defaults.pointText.circle) {
            if (Object.prototype.toString.call(temp) === '[object Object]') {
                var circle = svg.append('g')
                    .attr('class', 'zy-circle')
                    .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                    .selectAll('circle')
                    .data(defaults.store)
                    .enter()
                    .append('circle')
                    .attr('cx', line.x())
                    .attr('cy', line.y())
                    .attr('r', 3)
                    .attr('stroke', defaults.color[0])
                    .attr('fill', d3Config.circleFillColor)
                    .attr('stroke-width', d3Config.circleBorder)
                    .attr('data-x', function (d) {
                        return d.x;
                    })
                    .attr('data-y', function (d) {
                        return d.y;
                    })
                    .on('mouseover', function () {
                        d3.select(this)
                            .attr('r', 4);

                        if (defaults.tip.show) {
                            self.showTip(true, d3.event, this, defaults.tip, defaults.layout.margin);
                        }
                    })
                    .on('mouseout', function () {
                        d3.select(this)
                            .attr('r', 3);

                        if (defaults.tip.show) {
                            self.showTip(false);
                        }
                    });
            }
            // 多组
            if (Object.prototype.toString.call(temp) === '[object Array]') {
                for (var j = 0, lenth = defaults.data.length; j < lenth; j++) {
                    var circle_color = '#000000';
                    if (defaults.color[j]) {
                        circle_color = defaults.color[j];
                    }
                    var circles = svg.append('g')
                        .attr('class', 'zy-circle')
                        .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                        .selectAll('circle')
                        .data(defaults.store[j])
                        .enter()
                        .append('circle')
                        .attr('cx', line.x())
                        .attr('cy', line.y())
                        .attr('r', 3)
                        .attr('stroke', circle_color)
                        .attr('fill', d3Config.circleFillColor)
                        .attr('stroke-width', d3Config.circleBorder)
                        .attr('data-x', function (d) {
                            return d.x;
                        })
                        .attr('data-y', function (d) {
                            return d.y;
                        })
                        .on('mouseover', function () {
                            d3.select(this)
                                .attr('r', 4);

                            if (defaults.tip.show) {
                                self.showTip(true, d3.event, this, defaults.tip);
                            }
                        })
                        .on('mouseout', function () {
                            d3.select(this)
                                .attr('r', 3);

                            if (defaults.tip.show) {
                                self.showTip(false);
                            }
                        });
                }
            }
        }
        /*--------- 添加圆圈 - end ---------*/


        /*--------- 添加圆圈文字 - start ---------*/
        if (defaults.pointText.show) {
            // 单组
            if (Object.prototype.toString.call(temp) === '[object Object]') {
                svg.append('g')
                    .attr('class', 'zy-circle-text')
                    .attr('transform', 'translate(' + (defaults.layout.margin.left - 7) + ',' + (defaults.layout.margin.top - 13) + ')')
                    .selectAll('text')
                    .data(defaults.store)
                    .enter()
                    .append('text')
                    .text(function (d) {
                        if (defaults.pointText.render instanceof Function) {
                            return defaults.pointText.render(d.y);
                        } else {
                            return d.y;
                        }
                    })
                    .attr('x', line.x())
                    .attr('y', line.y())
                    .attr('fill', d3Config.axisColor)
                    .attr('font-size', d3Config.axisFontSize);
            }
            // 多组
            if (Object.prototype.toString.call(temp) === '[object Array]') {
                for (var k = 0, lenths = defaults.data.length; k < lenths; k++) {
                    svg.append('g')
                        .attr('class', 'zy-circle-text')
                        .attr('transform', 'translate(' + (defaults.layout.margin.left - 8) + ',' + (defaults.layout.margin.top - 10) + ')')
                        .selectAll('text')
                        .data(defaults.store[k])
                        .enter()
                        .append('text')
                        .text(function (d) {
                            if (defaults.pointText.render instanceof Function) {
                                return defaults.pointText.render(d.y);
                            } else {
                                return d.y;
                            }
                        })
                        .attr('x', line.x())
                        .attr('y', line.y())
                        .attr('fill', d3Config.axisColor)
                        .attr('font-size', d3Config.axisFontSize);
                }
            }
        }
        /*--------- 添加圆圈文字 - end ---------*/

        return true;
    },

    /**
     * 画柱状图 x 为序数值
     * @param config
     * @returns {boolean}
     */
    bar: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#61ade9'],              // 柱子颜色
            xAxis: {                         // x轴数据
                data: [],
                ticks: 0,
                index: [],
                show: true,
                render: ''
            },
            yAxis: {                         // y轴数据
                data: [],
                ticks: 0,
                index: [],
                show: true,
                render: ''
            },
            store: [],                       // 格式化后的数据
            data: [],                        // 原始数据集
            layout: {
                xtag: 'x轴',                 // x轴显示文本
                ytag: 'y轴',                 // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                           // 距容器边距
                xgrid: false,                // x轴网格
                ygrid: true                  // y轴网格
            },
            areaShow: false,                 // 是否显示区间背景(默认false不显示)
            area: [],                        // 区间背景
            pointText: {
                show: true,                  // 节点文字是否显示(默认true显示)
                render: ''                   // 渲染回调函数
            },
            tip: {                           // 显示提示
                show: true,
                xtag: 'x值',
                ytag: 'y值'
            }
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('area')) {
                    defaults.area = config['area'];
                }

                if (config.hasOwnProperty('areaShow')) {
                    defaults.areaShow = config['areaShow'];
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.render = config['pointText']['render'];
                    }
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('index')) {
                        defaults.xAxis.index = config['xAxis']['index'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('index')) {
                        defaults.yAxis.index = config['yAxis']['index'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var area = this.area(defaults.container);
        var width = area.width;
        var height = area.height;

        // get axis data
        var axisData = this.axisData(defaults.data);

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x.data;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y.data;
        }

        if (defaults.store.length === 0) {
            defaults.store = axisData.store;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.x.ticks;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.y.ticks;
        }

        // set axis index
        if (defaults.xAxis.index.length === 0) {
            defaults.xAxis.index = axisData.x.index;
        }

        if (defaults.yAxis.index.length === 0) {
            defaults.yAxis.index = axisData.y.index;
        }

        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale - ordinal
        var xScale_ordinal = d3.scaleOrdinal()
            .domain(defaults.xAxis.index)
            .range(defaults.xAxis.data);

        // xScale
        var xScale = d3.scaleLinear()
            .domain([d3.min(defaults.xAxis.index), d3.max(defaults.xAxis.index)])
            .range([0, (width - defaults.layout.margin.left - defaults.layout.margin.right)])
            .nice();

        // yScale
        var yScale = d3.scaleLinear()
            .domain([d3.min(defaults.yAxis.data), d3.max(defaults.yAxis.data)])
            .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
            .nice();

        // xAxis
        var xAxis = d3.axisBottom(xScale)
            .ticks(defaults.xAxis.ticks);

        // yAxis
        var yAxis = d3.axisLeft(yScale)
            .ticks(defaults.yAxis.ticks);

        // xGrid
        var xGrid = d3.axisBottom(xScale)
            .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom])
            .ticks(defaults.xAxis.ticks);

        // yGrid
        var yGrid = d3.axisRight(yScale)
            .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right])
            .ticks(defaults.yAxis.ticks);


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + (height - defaults.layout.margin.bottom) + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .text(function (d) {
                    if (defaults.xAxis.render instanceof Function) {
                        return defaults.xAxis.render(xScale_ordinal(d));
                    } else {
                        return xScale_ordinal(d);
                    }
                })
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

        }

        if (defaults.yAxis.show) {
            var yaxis = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yAxis);

            yaxis.selectAll('text')
                .text(function (d) {
                    if (defaults.yAxis.render instanceof Function) {
                        return defaults.yAxis.render(d);
                    } else {
                        return d;
                    }
                })
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            yaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + (width / 2) + ',' + (height - defaults.layout.margin.bottom / 10) + ')')
                .append('text')
                .text(defaults.layout.xtag)
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);
        }

        if (defaults.layout.ytag) {
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + (0) + ',' + (defaults.layout.margin.top / 2) + ')')
                .append('text')
                .text(defaults.layout.ytag)
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加柱状图 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-bar-group')
            .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
            .selectAll('rect')
            .data(defaults.store)
            .enter()
            .append('rect')
            .attr('x', function (d, i) {
                return xScale(i) - 20 / 2;
            })
            .attr('y', function (d, i) {
                var min = yScale.domain()[0];
                return yScale(min);
            })
            .attr('fill', defaults.color)
            .on('mouseover', function () {
                if (defaults.tip.show) {
                    self.showTip(true, d3.event, this, defaults.tip);
                }
            })
            .on('mouseout', function () {
                if (defaults.tip.show) {
                    self.showTip(false);
                }
            })
            .attr('data-y', function (d) {
                return d.y;
            })
            .attr('data-x', function (d) {
                return d.x;
            })
            .attr('width', function (d, i) {
                return 20;
            })
            .attr('height', function (d, i) {
                return 0;
            })
            .transition()
            .duration(500)
            .attr('height', function (d, i) {
                return height - defaults.layout.margin.top - defaults.layout.margin.bottom - yScale(d.y);
            })
            .attr('y', function (d, i) {
                return yScale(d.y);
            });
        /*--------- 添加柱状图 - end ---------*/

        return true;
    },


    /**
     * 怪异模式柱状图 柱宽为刻度宽 y 轴有负数
     * @param config
     * @returns {boolean}
     */
    barFx: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#61ade9'],              // 柱子颜色
            xAxis: {                         // x轴数据
                data: [],
                ticks: 0,
                show: true,
                render: '',
                col: ''
            },
            yAxis: {                         // y轴数据
                data: [],
                ticks: 0,
                show: true,
                render: '',
                col: ''
            },
            store: [],                       // 格式化后的数据
            data: [],                        // 原始数据集
            layout: {
                xtag: 'x轴',                 // x轴显示文本
                ytag: 'y轴',                 // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                           // 距容器边距
                xgrid: false,                // x轴网格
                ygrid: true                  // y轴网格
            },
            tip: {                           // 显示提示
                show: false,
                xtag: 'x值',
                ytag: 'y值'
            },
            pointText: {
                show: false,                 // 上方提示
                render: ''
            }
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                    if (config['xAxis'].hasOwnProperty('col')) {
                        defaults.xAxis.col = config['xAxis']['col'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                    if (config['yAxis'].hasOwnProperty('col')) {
                        defaults.yAxis.col = config['yAxis']['col'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.render = config['pointText']['render'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var area = this.area(defaults.container);
        var width = area.width;
        var height = area.height;

        // get axis data
        var axisData = this.formartFx(defaults.data, {x: defaults.xAxis.col, y: defaults.yAxis.col});

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y;
        }

        if (defaults.store.length === 0) {
            defaults.store = axisData.store;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.ticks;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.ticks;
        }

        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale
        var xScale = d3.scaleLinear()
            .domain([d3.min(defaults.xAxis.data), d3.max(defaults.xAxis.data)])
            .range([0, (width - defaults.layout.margin.left - defaults.layout.margin.right)])
            .nice();

        // yScale
        var yScale = d3.scaleLinear()
            .domain([d3.min(defaults.yAxis.data), d3.max(defaults.yAxis.data)])
            .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
            .nice();

        // xAxis
        var xAxis = d3.axisBottom(xScale)
            .ticks(defaults.xAxis.ticks);

        // yAxis
        var yAxis = d3.axisLeft(yScale)
            .ticks(defaults.yAxis.ticks);

        // xGrid
        var xGrid = d3.axisBottom(xScale)
            .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom])
            .ticks(defaults.xAxis.ticks);

        // yGrid
        var yGrid = d3.axisRight(yScale)
            .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right])
            .ticks(defaults.yAxis.ticks);


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + (height - defaults.layout.margin.bottom) + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.yAxis.show) {
            var yaxis = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yAxis);

            yaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            yaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + (width / 2) + ',' + (height - defaults.layout.margin.bottom / 10) + ')')
                .append('text')
                .text(defaults.layout.xtag);
        }

        if (defaults.layout.ytag) {
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + (0) + ',' + (defaults.layout.margin.top / 2) + ')')
                .append('text')
                .text(defaults.layout.ytag);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加柱状图 - start ---------*/
        var ticks_w = 0;
        svg.append('g')
            .attr('class', 'zy-bar-group')
            .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
            .selectAll('rect')
            .data(defaults.store)
            .enter()
            .append('rect')
            .attr('x', function (d, i) {
                return xScale(d.x);
            })
            .attr('y', function (d, i) {
                var min = yScale.domain()[0];
                return yScale(min);
            })
            .attr('fill', function (d, i) {
                if (d.ys > 0) {
                    return defaults.color[0];
                } else {
                    return defaults.color[1]
                }
            })
            .attr('data-x', function (d) {
                return d.x;
            })
            .attr('data-y', function (d) {
                return d.ys;
            })
            .attr('width', function (d, i) {
                ticks_w = (width - defaults.layout.margin.left) / ((xaxis.selectAll('line')._groups[0].length) - 1);
                return ticks_w;
            })
            .attr('height', function (d, i) {
                return 0;
            })
            .transition()
            .duration(500)
            .attr('y', function (d, i) {
                return yScale(d.y);
            })
            .attr('height', function (d, i) {
                return height - defaults.layout.margin.top - defaults.layout.margin.bottom - yScale(d.y);
            });
        /*--------- 添加柱状图 - end ---------*/


        /*--------- 添加柱状下方文字 - start ---------*/
        if (defaults.pointText.show) {
            svg.append('g')
                .attr('class', 'zy-bar-text')
                .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
                .selectAll('text')
                .data(defaults.store)
                .enter()
                .append('text')
                .attr('x', function (d, i) {
                    return (xScale(d.x) + (ticks_w / 3));
                })
                .attr('y', function (d, i) {
                    return height - defaults.layout.margin.bottom / 1.2;
                })
                .text(function (d) {
                    if (defaults.pointText.render instanceof Function) {
                        return defaults.pointText.render(d.ys);
                    } else {
                        return d.ys;
                    }
                })
                .attr('fill', function (d, i) {
                    if (d.ys > 0) {
                        return defaults.color[0];
                    } else {
                        return defaults.color[1]
                    }
                })
                .attr('font-size', d3Config.axisFontSize);
        }
        /*--------- 添加柱状下方文字 - end ---------*/

        return true;
    },


    /**
     * 怪异模式柱状图 y 轴为文本 横向柱子
     * @param config
     * @returns {boolean}
     */
    barVx: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#61ade9'],              // 柱子颜色
            xAxis: {                         // x轴数据
                data: [],
                ticks: 0,
                index: [],
                show: true,
                render: ''
            },
            yAxis: {                         // y轴数据
                data: [],
                ticks: 0,
                index: [],
                show: true,
                render: ''
            },
            store: [],                       // 格式化后的数据
            data: [],                        // 原始数据集
            layout: {
                xtag: 'x轴',                 // x轴显示文本
                ytag: 'y轴',                 // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                           // 距容器边距
                xgrid: false,                // x轴网格
                ygrid: true                  // y轴网格
            },
            areaShow: false,                 // 是否显示区间背景(默认false不显示)
            area: [],                        // 区间背景
            pointText: {
                show: true,                  // 节点文字是否显示(默认true显示)
                render: ''                   // 渲染回调函数
            },
            tip: {                           // 显示提示
                show: true,
                xtag: 'x值',
                ytag: 'y值'
            }
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('area')) {
                    defaults.area = config['area'];
                }

                if (config.hasOwnProperty('areaShow')) {
                    defaults.areaShow = config['areaShow'];
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.render = config['pointText']['render'];
                    }
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('index')) {
                        defaults.xAxis.index = config['xAxis']['index'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('index')) {
                        defaults.yAxis.index = config['yAxis']['index'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var area = this.area(defaults.container);
        var width = area.width;
        var height = area.height;

        // get axis data
        var axisData = this.axisData(defaults.data);

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x.data;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y.data;
        }

        if (defaults.xAxis.data.length > 0) {
            for (var idx = 0, len_idx = defaults.xAxis.data.length; idx < len_idx; idx++) {
                defaults.xAxis.data[idx] = parseFloat(defaults.xAxis.data[idx]);
            }
        }

        if (defaults.store.length === 0) {
            defaults.store = axisData.store;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.x.ticks;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.y.ticks;
        }

        // set axis index
        if (defaults.xAxis.index.length === 0) {
            defaults.xAxis.index = axisData.x.index;
        }

        if (defaults.yAxis.index.length === 0) {
            defaults.yAxis.index = axisData.y.index;
        }


        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale
        var xScale = d3.scaleLinear()
            .domain([d3.min(defaults.xAxis.data), d3.max(defaults.xAxis.data)])
            .range([0, (width - defaults.layout.margin.left - defaults.layout.margin.right)])
            .nice();

        // yScale
        var yScale = d3.scaleBand()
            .domain(defaults.yAxis.data)
            .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
            .paddingInner(1);

        // xAxis
        var xAxis = d3.axisBottom(xScale)
            .ticks(defaults.xAxis.ticks);

        // yAxis
        var yAxis = d3.axisLeft(yScale)
            .ticks(defaults.yAxis.ticks);

        // xGrid
        var xGrid = d3.axisBottom(xScale)
            .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom])
            .ticks(defaults.xAxis.ticks);

        // yGrid
        var yGrid = d3.axisRight(yScale)
            .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right])
            .ticks(defaults.yAxis.ticks);


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + (height - defaults.layout.margin.bottom) + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

        }

        if (defaults.yAxis.show) {
            var yaxis = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yAxis);

            yaxis.selectAll('text')
                .text(function (d) {
                    if(defaults.yAxis.render instanceof Function){
                        return defaults.yAxis.render(d);
                    }else{
                        return d;
                    }
                })
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            yaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + (width / 2) + ',' + (height - defaults.layout.margin.bottom / 10) + ')')
                .append('text')
                .text(defaults.layout.xtag);
        }

        if (defaults.layout.ytag) {
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + (0) + ',' + (defaults.layout.margin.top / 2) + ')')
                .append('text')
                .text(defaults.layout.ytag);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加横向柱状图 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-bar-group')
            .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
            .selectAll('rect')
            .data(defaults.store)
            .enter()
            .append('rect')
            .attr('x', function () {
                return 1;
            })
            .attr('y', function (d, i) {
                return yScale(d.y) - 5;
            })
            .attr('height', function (d, i) {
                return 10;
            })
            .attr('width', function (d, i) {
                return xScale(d.x);
            })
            .attr('fill', defaults.color[0]);
        /*--------- 添加柱状图 - end ---------*/


        /*--------- 添加横向柱状图文字 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-bar-group')
            .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
            .selectAll('text')
            .data(defaults.data)
            .enter()
            .append('text')
            .attr('x', function (d) {
                return xScale(d.x) + 5;
            })
            .attr('y', function (d, i) {
                return yScale(d.y) + 5;
            })
            .text(function (d, i) {
                if (d.x != 0) {
                    return d.x;
                }
                return '';
            })
            .attr('font-size', d3Config.axisFontSize)

            .attr('fill', defaults.color[0]);
        /*--------- 添加柱状图 - end ---------*/

        return true;
    },


    /**
     * 范围 柱形图 4色
     * 假比热力图
     * @param config
     * @returns {boolean}
     */
    barColor: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#61ade9'],              // 柱子颜色
            xAxis: {                         // x轴数据
                data: [],
                ticks: 0,
                show: true,
                render: ''
            },
            yAxis: {                         // y轴数据
                data: [],
                ticks: 0,
                show: true,
                render: ''
            },
            store: [],                       // 格式化后的数据
            data: [],                        // 原始数据集
            layout: {
                xtag: 'x轴',                 // x轴显示文本
                ytag: 'y轴',                 // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                           // 距容器边距
                xgrid: false,                // x轴网格
                ygrid: true                  // y轴网格
            },
            areaShow: false,                 // 是否显示区间背景(默认false不显示)
            area: [],                        // 区间背景
            pointText: {
                show: true,                  // 节点文字是否显示(默认true显示)
                render: ''                   // 渲染回调函数
            },
            tip: {                           // 显示提示
                show: true,
                xtag: 'x值',
                ytag: 'y值'
            }
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('area')) {
                    defaults.area = config['area'];
                }

                if (config.hasOwnProperty('areaShow')) {
                    defaults.areaShow = config['areaShow'];
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.render = config['pointText']['render'];
                    }
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var area = this.area(defaults.container);
        var width = area.width;
        var height = area.height;

        // get axis data
        var axisData = this.formartX1X2YS(defaults.data, {x1: 'x1', x2: 'x2', y: 'y'});

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y;
        }

        if (defaults.store.length === 0) {
            defaults.store = axisData.store;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.x.length;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.y.length;
        }

        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale
        var xScale = d3.scaleLinear()
            .domain([d3.min(defaults.xAxis.data), d3.max(defaults.xAxis.data)])
            .range([0, (width - defaults.layout.margin.left - defaults.layout.margin.right)])
            .nice();

        // yScale
        var yScale = d3.scaleLinear()
            .domain([d3.min(defaults.yAxis.data), d3.max(defaults.yAxis.data)])
            .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
            .nice();

        // xAxis
        var xAxis = d3.axisBottom(xScale)
            .ticks(defaults.xAxis.ticks);

        // yAxis
        var yAxis = d3.axisLeft(yScale)
            .ticks(defaults.yAxis.ticks);

        // xGrid
        var xGrid = d3.axisBottom(xScale)
            .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom])
            .ticks(defaults.xAxis.ticks);

        // yGrid
        var yGrid = d3.axisRight(yScale)
            .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right])
            .ticks(defaults.yAxis.ticks);


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + (height - defaults.layout.margin.bottom) + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .text(function (d) {
                    if (defaults.xAxis.render instanceof Function) {
                        return defaults.xAxis.render(d);
                    } else {
                        return d;
                    }
                })
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

        }

        if (defaults.yAxis.show) {
            var yaxis = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yAxis);

            yaxis.selectAll('text')
                .text(function (d) {
                    if (defaults.yAxis.render instanceof Function) {
                        return defaults.yAxis.render(d);
                    } else {
                        return d;
                    }
                })
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            yaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + (width / 2) + ',' + (height - defaults.layout.margin.bottom / 10) + ')')
                .append('text')
                .text(defaults.layout.xtag)
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);
        }

        if (defaults.layout.ytag) {
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + (0) + ',' + (defaults.layout.margin.top / 2) + ')')
                .append('text')
                .text(defaults.layout.ytag)
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加柱状图 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-bar-group')
            .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
            .selectAll('rect')
            .data(defaults.store)
            .enter()
            .append('rect')
            .attr('x', function (d, i) {
                return xScale(d.x1) + 1;
            })
            .attr('y', function (d, i) {
                return yScale(d.y);
            })
            .attr('width', function (d, i) {
                return (xScale(d.x2) - xScale(d.x1));
            })
            .attr('height', function (d, i) {
                return (yScale(d.y));
            })
            .attr('fill', function (d) {
                switch (true) {
                    case (d.ys <= 10):
                        return defaults.color[0];
                        break;
                    case (d.ys > 10 && d.ys <= 50):
                        return defaults.color[1];
                        break;
                    case (d.ys > 50 && d.ys <= 100):
                        return defaults.color[2];
                        break;
                    case (d.ys > 100):
                        return defaults.color[3];
                        break;
                    default:
                        break;
                }
            });
        /*--------- 添加柱状图 - end ---------*/

        return true;
    },


    /**
     * 单轴散点图 y 值固定 x 为散点
     * 类似图钉效果 文字钉帽 单色
     * @param config
     * @returns {boolean}
     */
    sign: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#61ade9'],              // 柱子颜色
            xAxis: {                         // x轴数据
                data: [],
                ticks: 0,
                show: true,
                render: '',
                col: ''
            },
            yAxis: {                         // y轴数据
                data: [],
                ticks: 0,
                show: true,
                render: '',
                col: ''
            },
            store: [],                       // 格式化后的数据
            data: [],                        // 原始数据集
            layout: {
                xtag: 'x轴',                 // x轴显示文本
                ytag: 'y轴',                 // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                           // 距容器边距
                xgrid: false,                // x轴网格
                ygrid: false                 // y轴网格
            },
            tip: {                           // 显示提示
                show: true,
                xtag: 'x值',
                ytag: 'y值'
            },
            pointText: {
                show: false,
                render: ''
            },
            signText: ''
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('signText')) {
                    defaults.signText = config['signText'];
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                    if (config['xAxis'].hasOwnProperty('col')) {
                        defaults.xAxis.col = config['xAxis']['col'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                    if (config['yAxis'].hasOwnProperty('col')) {
                        defaults.yAxis.col = config['yAxis']['col'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.render = config['pointText']['render'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var area = this.area(defaults.container);
        var width = area.width;
        var height = area.height;

        // get axis data
        var axisData = this.formartSx(defaults.data, {x: defaults.xAxis.col, y: defaults.yAxis.col, ys: 'ys'});

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y;
        }

        if (defaults.store.length === 0) {
            defaults.store = axisData.store;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.ticks;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.ticks;
        }

        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale
        var xScale = d3.scaleLinear()
            .domain([d3.min(defaults.xAxis.data), d3.max(defaults.xAxis.data)])
            .range([0, (width - defaults.layout.margin.left - defaults.layout.margin.right)])
            .nice();

        // yScale
        var yScale = d3.scaleLinear()
            .domain([d3.min(defaults.yAxis.data), d3.max(defaults.yAxis.data)])
            .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
            .nice();

        // xAxis
        var xAxis = d3.axisBottom(xScale)
            .ticks(defaults.xAxis.ticks);

        // yAxis
        var yAxis = d3.axisLeft(yScale)
            .ticks(defaults.yAxis.ticks);

        // xGrid
        var xGrid = d3.axisBottom(xScale)
            .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom])
            .ticks(defaults.xAxis.ticks);

        // yGrid
        var yGrid = d3.axisRight(yScale)
            .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right])
            .ticks(defaults.yAxis.ticks);


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + (height - defaults.layout.margin.bottom) + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.yAxis.show) {
            var yaxis = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yAxis);

            yaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            yaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + (width / 2) + ',' + (height - defaults.layout.margin.bottom / 10) + ')')
                .append('text')
                .text(defaults.layout.xtag);
        }

        if (defaults.layout.ytag) {
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + (0) + ',' + (defaults.layout.margin.top / 2) + ')')
                .append('text')
                .text(defaults.layout.ytag);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加钉子 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-hit-group')
            .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
            .selectAll('rect')
            .data(defaults.store)
            .enter()
            .append('rect')
            .attr('x', function (d, i) {
                return xScale(d.x) - 1;
            })
            .attr('y', function (d, i) {
                return yScale(d.y);
            })
            .attr('width', d3Config.signCircleBorder)
            .attr('height', function (d, i) {
                return (height - defaults.layout.margin.top - defaults.layout.margin.bottom) - yScale(d.y);
            })
            .attr('fill', defaults.color[0])
            .attr('data-x', function (d) {
                return d.x;
            })
            .attr('data-y', function (d) {
                return d.ys;
            });
        /*--------- 添加钉子 - end ---------*/

        var line = d3.line()
            .x(function (d) {
                return xScale(d.x);
            })
            .y(function (d) {
                return yScale(d.y);
            });

        /*--------- 添加钉冒 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-hat-group')
            .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
            .selectAll('circle')
            .data(defaults.store)
            .enter()
            .append('circle')
            .attr('r', 13)
            .attr('cx', line.x())
            .attr('cy', line.y())
            .attr('fill', d3Config.circleFillColor)
            .attr('stroke-width', d3Config.signCircleBorder)
            .attr('stroke', defaults.color[1])
            .attr('data-x', function (d) {
                return d.x;
            })
            .attr('data-y', function (d) {
                return d.ys;
            });
        /*--------- 添加钉冒 - end ---------*/

        var line2 = d3.line()
            .x(function (d) {
                return xScale(d.x) - 8;
            })
            .y(function (d) {
                return yScale(d.y) + 5;
            });

        /*--------- 添加钉文字 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-hat-text')
            .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
            .selectAll('text')
            .data(defaults.store)
            .enter()
            .append('text')
            .attr('x', line2.x())
            .attr('y', line2.y())
            .attr('fill', defaults.color[2])
            .attr('style', 'font-size:16px;font-weight:bold')
            .text(function (d) {
                if (defaults.signText instanceof Function) {
                    return defaults.signText(d);
                } else {
                    return '未知';
                }
            });
        /*--------- 添加钉文字 - end ---------*/

        return true;
    },

    /**
     * 拷贝至 sign
     * 实心钉帽 文字在上部 双色
     * 可能只适用于交直流干扰 may be
     * @param config
     * @returns {boolean}
     */
    signFx: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#61ade9'],              // 柱子颜色
            xAxis: {                         // x轴数据
                data: [],
                ticks: 0,
                show: true,
                render: '',
                col: ''
            },
            yAxis: {                         // y轴数据
                data: [],
                ticks: 0,
                show: true,
                render: '',
                col: ''
            },
            store: [],                       // 格式化后的数据
            data: [],                        // 原始数据集
            layout: {
                xtag: 'x轴',                 // x轴显示文本
                ytag: 'y轴',                 // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                           // 距容器边距
                xgrid: false,                // x轴网格
                ygrid: false                 // y轴网格
            },
            tip: {                           // 显示提示
                show: true,
                xtag: 'x值',
                ytag: 'y值'
            },
            signText: '',                    // 标识文字function
            circleRender: '',
            pointText: {
                show: true,
                render: ''
            }
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('signText')) {
                    defaults.signText = config['signText'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('circleRender')) {
                    defaults.circleRender = config['circleRender'];
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                    if (config['xAxis'].hasOwnProperty('col')) {
                        defaults.xAxis.col = config['xAxis']['col'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                    if (config['yAxis'].hasOwnProperty('col')) {
                        defaults.yAxis.col = config['yAxis']['col'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.xtag = config['pointText']['render'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var area = this.area(defaults.container);
        var width = area.width;
        var height = area.height;

        // get axis data
        var axisData = this.formartSx(defaults.data, {x: defaults.xAxis.col, y: defaults.yAxis.col, ys: 'ys'});

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y;
        }

        if (defaults.store.length === 0) {
            defaults.store = axisData.store;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.ticks;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.ticks;
        }

        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale
        var xScale = d3.scaleLinear()
            .domain([d3.min(defaults.xAxis.data), d3.max(defaults.xAxis.data)])
            .range([0, (width - defaults.layout.margin.left - defaults.layout.margin.right)])
            .nice();

        // yScale
        var yScale = d3.scaleLinear()
            .domain([d3.min(defaults.yAxis.data), d3.max(defaults.yAxis.data)])
            .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
            .nice();

        // xAxis
        var xAxis = d3.axisBottom(xScale)
            .ticks(defaults.xAxis.ticks);

        // yAxis
        var yAxis = d3.axisLeft(yScale)
            .ticks(defaults.yAxis.ticks);

        // xGrid
        var xGrid = d3.axisBottom(xScale)
            .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom])
            .ticks(defaults.xAxis.ticks);

        // yGrid
        var yGrid = d3.axisRight(yScale)
            .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right])
            .ticks(defaults.yAxis.ticks);


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + (height - defaults.layout.margin.bottom) + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.yAxis.show) {
            var yaxis = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yAxis);

            yaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            yaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + (width / 2) + ',' + (height - defaults.layout.margin.bottom / 10) + ')')
                .append('text')
                .text(defaults.layout.xtag);
        }

        if (defaults.layout.ytag) {
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + (0) + ',' + (defaults.layout.margin.top / 2) + ')')
                .append('text')
                .text(defaults.layout.ytag);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加钉子 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-hit-group')
            .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
            .selectAll('rect')
            .data(defaults.store)
            .enter()
            .append('rect')
            .attr('x', function (d, i) {
                return xScale(d.x) - 1;
            })
            .attr('y', function (d, i) {
                return yScale(d.y);
            })
            .attr('width', d3Config.signCircleBorder)
            .attr('height', function (d, i) {
                return (height - defaults.layout.margin.top - defaults.layout.margin.bottom) - yScale(d.y);
            })
            .attr('fill', function (d) {
                if (defaults.circleRender instanceof Function) {
                    return defaults.circleRender(d);
                } else {
                    return defaults.color[0];
                }
            })
            .attr('data-x', function (d) {
                return d.x;
            })
            .attr('data-y', function (d) {
                return d.ys;
            });
        /*--------- 添加钉子 - end ---------*/

        var line = d3.line()
            .x(function (d) {
                return xScale(d.x);
            })
            .y(function (d) {
                return yScale(d.y);
            });

        /*--------- 添加钉冒 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-hat-group')
            .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
            .selectAll('circle')
            .data(defaults.store)
            .enter()
            .append('circle')
            .attr('r', 9)
            .attr('cx', line.x())
            .attr('cy', line.y())
            .attr('fill', function (d) {
                if (defaults.circleRender instanceof Function) {
                    return defaults.circleRender(d);
                } else {
                    return defaults.color[0];
                }
            })
            .attr('stroke-width', d3Config.signCircleBorder)
            .attr('stroke', function (d) {
                if (defaults.circleRender instanceof Function) {
                    return defaults.circleRender(d);
                } else {
                    return defaults.color[0];
                }
            })
            .attr('data-x', function (d) {
                return d.x;
            })
            .attr('data-y', function (d) {
                return d.ys;
            });
        /*--------- 添加钉冒 - end ---------*/

        var line2 = d3.line()
            .x(function (d) {
                return xScale(d.x) - 10;
            })
            .y(function (d) {
                return yScale(d.y) - 20;
            });

        /*--------- 添加钉文字 - start ---------*/
        if (defaults.pointText.show) {
            svg.append('g')
                .attr('class', 'zy-hat-text')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .selectAll('text')
                .data(defaults.store)
                .enter()
                .append('text')
                .attr('x', line2.x())
                .attr('y', line2.y())
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize)
                .text(function (d) {
                    if (defaults.signText instanceof Function) {
                        return defaults.signText(d);
                    } else {
                        return '未知';
                    }
                });
        }
        /*--------- 添加钉文字 - end ---------*/

        return true;
    },


    /**
     * 拷贝至 signFx
     * 实心钉帽 文字在上部 单色
     * @param config
     * @returns {boolean}
     */
    signVx: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#61ade9'],              // 柱子颜色
            xAxis: {                         // x轴数据
                data: [],
                ticks: 0,
                show: true,
                render: '',
                col: ''
            },
            yAxis: {                         // y轴数据
                data: [],
                ticks: 0,
                show: true,
                render: '',
                col: ''
            },
            store: [],                       // 格式化后的数据
            data: [],                        // 原始数据集
            layout: {
                xtag: 'x轴',                 // x轴显示文本
                ytag: 'y轴',                 // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                           // 距容器边距
                xgrid: false,                // x轴网格
                ygrid: false                 // y轴网格
            },
            tip: {                           // 显示提示
                show: true,
                xtag: 'x值',
                ytag: 'y值'
            },
            pointText: {
                show: true,
                render: ''
            },
            signText: ''
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('signText')) {
                    defaults.signText = config['signText'];
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                    if (config['xAxis'].hasOwnProperty('col')) {
                        defaults.xAxis.col = config['xAxis']['col'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                    if (config['yAxis'].hasOwnProperty('col')) {
                        defaults.yAxis.col = config['yAxis']['col'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.render = config['pointText']['render'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var area = this.area(defaults.container);
        var width = area.width;
        var height = area.height;

        // get axis data
        var axisData = this.formartSx(defaults.data, {x: defaults.xAxis.col, y: defaults.yAxis.col, ys: 'ys'});

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y;
        }

        if (defaults.store.length === 0) {
            defaults.store = axisData.store;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.ticks;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.ticks;
        }

        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale
        var xScale = d3.scaleLinear()
            .domain([d3.min(defaults.xAxis.data), d3.max(defaults.xAxis.data)])
            .range([0, (width - defaults.layout.margin.left - defaults.layout.margin.right)])
            .nice();

        // yScale
        var yScale = d3.scaleLinear()
            .domain([d3.min(defaults.yAxis.data), d3.max(defaults.yAxis.data)])
            .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
            .nice();

        // xAxis
        var xAxis = d3.axisBottom(xScale)
            .ticks(defaults.xAxis.ticks);

        // yAxis
        var yAxis = d3.axisLeft(yScale)
            .ticks(defaults.yAxis.ticks);

        // xGrid
        var xGrid = d3.axisBottom(xScale)
            .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom])
            .ticks(defaults.xAxis.ticks);

        // yGrid
        var yGrid = d3.axisRight(yScale)
            .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right])
            .ticks(defaults.yAxis.ticks);


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + (height - defaults.layout.margin.bottom) + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.yAxis.show) {
            var yaxis = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yAxis);

            yaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            yaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + (width / 2) + ',' + (height - defaults.layout.margin.bottom / 10) + ')')
                .append('text')
                .text(defaults.layout.xtag);
        }

        if (defaults.layout.ytag) {
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + (0) + ',' + (defaults.layout.margin.top / 2) + ')')
                .append('text')
                .text(defaults.layout.ytag);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加钉子 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-hit-group')
            .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
            .selectAll('rect')
            .data(defaults.store)
            .enter()
            .append('rect')
            .attr('x', function (d, i) {
                return xScale(d.x) - 1;
            })
            .attr('y', function (d, i) {
                return yScale(d.y);
            })
            .attr('width', d3Config.signCircleBorder)
            .attr('height', function (d, i) {
                return (height - defaults.layout.margin.top - defaults.layout.margin.bottom) - yScale(d.y);
            })
            .attr('fill', defaults.color[0])
            .attr('data-x', function (d) {
                return d.x;
            })
            .attr('data-y', function (d) {
                return d.ys;
            });
        /*--------- 添加钉子 - end ---------*/

        var line = d3.line()
            .x(function (d) {
                return xScale(d.x);
            })
            .y(function (d) {
                return yScale(d.y);
            });

        /*--------- 添加钉冒 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-hat-group')
            .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
            .selectAll('circle')
            .data(defaults.store)
            .enter()
            .append('circle')
            .attr('r', 9)
            .attr('cx', line.x())
            .attr('cy', line.y())
            .attr('fill', defaults.color[0])
            .attr('stroke-width', d3Config.signCircleBorder)
            .attr('stroke', defaults.color[0])
            .attr('data-x', function (d) {
                return d.x;
            })
            .attr('data-y', function (d) {
                return d.ys;
            });
        /*--------- 添加钉冒 - end ---------*/

        var line2 = d3.line()
            .x(function (d) {
                return xScale(d.x) - 10;
            })
            .y(function (d) {
                return yScale(d.y) - 20;
            });

        /*--------- 添加钉文字 - start ---------*/
        if (defaults.pointText.show) {
            svg.append('g')
                .attr('class', 'zy-hat-text')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .selectAll('text')
                .data(defaults.store)
                .enter()
                .append('text')
                .attr('x', line2.x())
                .attr('y', line2.y())
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize)
                .text(function (d) {
                    if (defaults.signText instanceof Function) {
                        return defaults.signText(d);
                    } else {
                        return '未知';
                    }
                });
        }
        /*--------- 添加钉文字 - end ---------*/

        return true;
    },


    /**
     * 拷贝至 signVx
     * 图形钉帽 无文字
     * 可能只适用于 (定标点 - 测试桩)
     * @param config
     * @returns {boolean}
     */
    signSx: function (config) {

        var self = this;

        // default setting
        var defaults = {
            container: '',                   // svg容器
            color: ['#61ade9'],              // 柱子颜色
            xAxis: {                         // x轴数据
                data: [],
                ticks: 0,
                show: true,
                render: '',
                col: ''
            },
            yAxis: {                         // y轴数据
                data: [],
                ticks: 0,
                show: true,
                render: '',
                col: ''
            },
            store: [],                       // 格式化后的数据
            data: [],                        // 原始数据集
            layout: {
                xtag: 'x轴',                 // x轴显示文本
                ytag: 'y轴',                 // y轴显示文本
                margin: {
                    left: 30,
                    right: 30,
                    top: 30,
                    bottom: 30
                },                           // 距容器边距
                xgrid: false,                // x轴网格
                ygrid: false                 // y轴网格
            },
            tip: {                           // 显示提示
                show: true,
                xtag: 'x值',
                ytag: 'y值'
            },
            pointText: {
                show: true,
                render: ''
            },
            signText: ''
        };

        // check config
        if (config) {
            if (Object.prototype.toString.call(config) === '[object Object]') {
                if (config.hasOwnProperty('container')) {
                    defaults.container = config['container'];
                } else {
                    throw new Error('DOM容器不存在!');
                }

                if (config.hasOwnProperty('data')) {
                    defaults.data = config['data'];
                } else {
                    throw new Error('绘制数据不存在!');
                }

                if (config.hasOwnProperty('layout')) {
                    defaults.layout = config['layout'];
                }

                if (config.hasOwnProperty('color')) {
                    defaults.color = config['color'];
                }

                if (config.hasOwnProperty('signText')) {
                    defaults.signText = config['signText'];
                }

                if (config.hasOwnProperty('xAxis')) {
                    if (config['xAxis'].hasOwnProperty('data')) {
                        defaults.xAxis.data = config['xAxis']['data'];
                    }
                    if (config['xAxis'].hasOwnProperty('ticks')) {
                        defaults.xAxis.ticks = config['xAxis']['ticks'];
                    }
                    if (config['xAxis'].hasOwnProperty('show')) {
                        defaults.xAxis.show = config['xAxis']['show'];
                    }
                    if (config['xAxis'].hasOwnProperty('render')) {
                        defaults.xAxis.render = config['xAxis']['render'];
                    }
                    if (config['xAxis'].hasOwnProperty('col')) {
                        defaults.xAxis.col = config['xAxis']['col'];
                    }
                }

                if (config.hasOwnProperty('yAxis')) {
                    if (config['yAxis'].hasOwnProperty('data')) {
                        defaults.yAxis.data = config['yAxis']['data'];
                    }
                    if (config['yAxis'].hasOwnProperty('ticks')) {
                        defaults.yAxis.ticks = config['yAxis']['ticks'];
                    }
                    if (config['yAxis'].hasOwnProperty('show')) {
                        defaults.yAxis.show = config['yAxis']['show'];
                    }
                    if (config['yAxis'].hasOwnProperty('render')) {
                        defaults.yAxis.render = config['yAxis']['render'];
                    }
                    if (config['yAxis'].hasOwnProperty('col')) {
                        defaults.yAxis.col = config['yAxis']['col'];
                    }
                }

                if (config.hasOwnProperty('tip')) {
                    if (config['tip'].hasOwnProperty('show')) {
                        defaults.tip.show = config['tip']['show'];
                    }
                    if (config['tip'].hasOwnProperty('xtag')) {
                        defaults.tip.xtag = config['tip']['xtag'];
                    }
                    if (config['tip'].hasOwnProperty('ytag')) {
                        defaults.tip.ytag = config['tip']['ytag'];
                    }
                }

                if (config.hasOwnProperty('pointText')) {
                    if (config['pointText'].hasOwnProperty('show')) {
                        defaults.pointText.show = config['pointText']['show'];
                    }
                    if (config['pointText'].hasOwnProperty('render')) {
                        defaults.pointText.render = config['pointText']['render'];
                    }
                }
            } else {
                throw new Error('配置项数据格式不正确!');
            }
        } else {
            throw new Error('缺少配置项数据!');
        }

        // get width & height
        var area = this.area(defaults.container);
        var width = area.width;
        var height = area.height;

        // get axis data
        var axisData = this.formartSx(defaults.data, {x: defaults.xAxis.col, y: defaults.yAxis.col, ys: 'ys'});

        // set axis data
        if (defaults.xAxis.data.length === 0) {
            defaults.xAxis.data = axisData.x;
        }

        if (defaults.yAxis.data.length === 0) {
            defaults.yAxis.data = axisData.y;
        }

        if (defaults.store.length === 0) {
            defaults.store = axisData.store;
        }

        // set axis ticks
        if (defaults.xAxis.ticks === 0) {
            defaults.xAxis.ticks = axisData.ticks;
        }

        if (defaults.yAxis.ticks === 0) {
            defaults.yAxis.ticks = axisData.ticks;
        }

        /*--------------------------- d3 ---------------------------*/
        // svg
        var svg = d3.select('#' + defaults.container)
            .append('svg')
            .attr('width', width)
            .attr('height', height);

        // xScale
        var xScale = d3.scaleLinear()
            .domain([d3.min(defaults.xAxis.data), d3.max(defaults.xAxis.data)])
            .range([0, (width - defaults.layout.margin.left - defaults.layout.margin.right)])
            .nice();

        // yScale
        var yScale = d3.scaleLinear()
            .domain([d3.min(defaults.yAxis.data), d3.max(defaults.yAxis.data)])
            .range([height - defaults.layout.margin.top - defaults.layout.margin.bottom, 0])
            .nice();

        // xAxis
        var xAxis = d3.axisBottom(xScale)
            .ticks(defaults.xAxis.ticks);

        // yAxis
        var yAxis = d3.axisLeft(yScale)
            .ticks(defaults.yAxis.ticks);

        // xGrid
        var xGrid = d3.axisBottom(xScale)
            .tickSize([height - defaults.layout.margin.top - defaults.layout.margin.bottom])
            .ticks(defaults.xAxis.ticks);

        // yGrid
        var yGrid = d3.axisRight(yScale)
            .tickSize([width - defaults.layout.margin.left - defaults.layout.margin.right])
            .ticks(defaults.yAxis.ticks);


        /*--------- 添加xy轴 网格 - start ---------*/
        if (defaults.layout.xgrid) {
            var xgrid = svg.append('g')
                .attr('class', 'zy-x-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(xGrid);

            xgrid.selectAll('text')
                .text('');

            xgrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            xgrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.layout.ygrid) {
            var ygrid = svg.append('g')
                .attr('class', 'zy-y-grid')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yGrid);

            ygrid.selectAll('text')
                .text('');

            ygrid.selectAll('line')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);

            ygrid.selectAll('path')
                .attr('stroke', d3Config.gridColor)
                .attr('shape-rendering', d3Config.lineRender);
        }
        /*--------- 添加xy轴 网格 - end ---------*/


        /*--------- 添加xy轴 - start ---------*/
        if (defaults.xAxis.show) {
            var xaxis = svg.append('g')
                .attr('class', 'zy-x-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + (height - defaults.layout.margin.bottom) + ')')
                .call(xAxis);

            xaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            xaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            xaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);
        }

        if (defaults.yAxis.show) {
            var yaxis = svg.append('g')
                .attr('class', 'zy-y-axis')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .call(yAxis);

            yaxis.selectAll('text')
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize);

            yaxis.selectAll('line')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

            yaxis.selectAll('path')
                .attr('stroke', d3Config.axisColor)
                .attr('shape-rendering', d3Config.lineRender);

        }
        /*--------- 添加xy轴 - end ---------*/


        /*--------- 添加xy轴文本描述 - start ---------*/
        if (defaults.layout.xtag) {
            svg.append('g')
                .attr('class', 'zy-x-axis-text')
                .attr('transform', 'translate(' + (width / 2) + ',' + (height - defaults.layout.margin.bottom / 10) + ')')
                .append('text')
                .text(defaults.layout.xtag);
        }

        if (defaults.layout.ytag) {
            svg.append('g')
                .attr('class', 'zy-y-axis-text')
                .attr('transform', 'translate(' + (0) + ',' + (defaults.layout.margin.top / 2) + ')')
                .append('text')
                .text(defaults.layout.ytag);
        }
        /*--------- 添加xy轴文本描述 - end ---------*/


        /*--------- 添加钉子 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-hit-group')
            .attr('transform', 'translate(' + (defaults.layout.margin.left) + ',' + (defaults.layout.margin.top) + ')')
            .selectAll('rect')
            .data(defaults.store)
            .enter()
            .append('rect')
            .attr('x', function (d, i) {
                return xScale(d.x) - 1;
            })
            .attr('y', function (d, i) {
                return yScale(d.y) + 12;
            })
            .attr('width', d3Config.signCircleBorder)
            .attr('height', function (d, i) {
                return (height - defaults.layout.margin.top - defaults.layout.margin.bottom - 12) - yScale(d.y);
            })
            .attr('fill', function (d) {
                if (d.ys === 'MARK') {
                    return defaults.color[0];
                } else {
                    return defaults.color[1];
                }
            })
            .attr('data-x', function (d) {
                return d.x;
            })
            .attr('data-y', function (d) {
                return d.ys;
            });
        /*--------- 添加钉子 - end ---------*/

        var line = d3.line()
            .x(function (d) {
                return xScale(d.x) - 6;
            })
            .y(function (d) {
                return yScale(d.y);
            });

        /*--------- 添加钉冒 - start ---------*/
        svg.append('g')
            .attr('class', 'zy-hat-group')
            .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
            .selectAll('circle')
            .data(defaults.store)
            .enter()
            .append('rect')
            .attr('width', 12)
            .attr('height', 12)
            .attr('rx', function (d) {
                if (d.ys === 'MARK') {
                    return 12;
                } else {
                    return 0;
                }
            })
            .attr('ry', function (d) {
                if (d.ys === 'MARK') {
                    return 12;
                } else {
                    return 0;
                }
            })
            .attr('x', line.x())
            .attr('y', line.y())
            .attr('fill', 'none')
            .attr('stroke-width', d3Config.signCircleBorder)
            .attr('stroke', function (d) {
                if (d.ys === 'MARK') {
                    return defaults.color[0];
                } else {
                    return defaults.color[1];
                }
            })
            .attr('data-x', function (d) {
                return d.x;
            })
            .attr('data-y', function (d) {
                return d.ys;
            });
        /*--------- 添加钉冒 - end ---------*/

        var line2 = d3.line()
            .x(function (d) {
                return xScale(d.x) - 10;
            })
            .y(function (d) {
                return yScale(d.y) - 20;
            });

        /*--------- 添加钉文字 - start ---------*/
        if (defaults.pointText.show) {
            svg.append('g')
                .attr('class', 'zy-hat-text')
                .attr('transform', 'translate(' + defaults.layout.margin.left + ',' + defaults.layout.margin.top + ')')
                .selectAll('text')
                .data(defaults.store)
                .enter()
                .append('text')
                .attr('x', line2.x())
                .attr('y', line2.y())
                .attr('fill', d3Config.axisColor)
                .attr('font-size', d3Config.axisFontSize)
                .text(function (d) {
                    if (defaults.signText instanceof Function) {
                        return defaults.signText(d);
                    } else {
                        return '未知';
                    }
                });
        }
        /*--------- 添加钉文字 - end ---------*/

        return true;
    }

};